Linux v4.4.13
This commit is contained in:
parent
3aec64cb4f
commit
885cb3a4ac
|
@ -1,227 +0,0 @@
|
|||
From c18d8f5095715c56bb3cd9cba64242542632054b Mon Sep 17 00:00:00 2001
|
||||
From: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
Date: Wed, 16 Mar 2016 13:33:34 -0500
|
||||
Subject: rtlwifi: rtl8723be: Add antenna select module parameter
|
||||
|
||||
A number of new laptops have been delivered with only a single antenna.
|
||||
In principle, this is OK; however, a problem arises when the on-board
|
||||
EEPROM is programmed to use the other antenna connection. The option
|
||||
of opening the computer and moving the connector is not always possible
|
||||
as it will void the warranty in some cases. In addition, this solution
|
||||
breaks the Windows driver when the box dual boots Linux and Windows.
|
||||
|
||||
A fix involving a new module parameter has been developed. This commit
|
||||
adds the new parameter and implements the changes needed for the driver.
|
||||
|
||||
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
Cc: Stable <stable@vger.kernel.org> [V4.0+]
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 5 +++++
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 3 +++
|
||||
drivers/net/wireless/realtek/rtlwifi/wifi.h | 3 +++
|
||||
3 files changed, 11 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
|
||||
index c983d2f..5a3df91 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
|
||||
@@ -2684,6 +2684,7 @@ void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
|
||||
bool auto_load_fail, u8 *hwinfo)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
+ struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params;
|
||||
u8 value;
|
||||
u32 tmpu_32;
|
||||
|
||||
@@ -2702,6 +2703,10 @@ void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
|
||||
rtlpriv->btcoexist.btc_info.ant_num = ANT_X2;
|
||||
}
|
||||
|
||||
+ /* override ant_num / ant_path */
|
||||
+ if (mod_params->ant_sel)
|
||||
+ rtlpriv->btcoexist.btc_info.ant_num =
|
||||
+ (mod_params->ant_sel == 1 ? ANT_X2 : ANT_X1);
|
||||
}
|
||||
|
||||
void rtl8723be_bt_reg_init(struct ieee80211_hw *hw)
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
|
||||
index a78eaed..2101793 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
|
||||
@@ -273,6 +273,7 @@ static struct rtl_mod_params rtl8723be_mod_params = {
|
||||
.msi_support = false,
|
||||
.disable_watchdog = false,
|
||||
.debug = DBG_EMERG,
|
||||
+ .ant_sel = 0,
|
||||
};
|
||||
|
||||
static struct rtl_hal_cfg rtl8723be_hal_cfg = {
|
||||
@@ -394,6 +395,7 @@ module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444);
|
||||
module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444);
|
||||
module_param_named(disable_watchdog, rtl8723be_mod_params.disable_watchdog,
|
||||
bool, 0444);
|
||||
+module_param_named(ant_sel, rtl8723be_mod_params.ant_sel, int, 0444);
|
||||
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
|
||||
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
|
||||
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
|
||||
@@ -402,6 +404,7 @@ MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n");
|
||||
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
|
||||
MODULE_PARM_DESC(disable_watchdog,
|
||||
"Set to 1 to disable the watchdog (default 0)\n");
|
||||
+MODULE_PARM_DESC(ant_sel, "Set to 1 or 2 to force antenna number (default 0)\n");
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
|
||||
index 554d814..93bd7fc 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
|
||||
@@ -2246,6 +2246,9 @@ struct rtl_mod_params {
|
||||
|
||||
/* default 0: 1 means do not disable interrupts */
|
||||
bool int_clear;
|
||||
+
|
||||
+ /* select antenna */
|
||||
+ int ant_sel;
|
||||
};
|
||||
|
||||
struct rtl_hal_usbint_cfg {
|
||||
--
|
||||
cgit v0.12
|
||||
|
||||
From baa1702290953295e421f0f433e2b1ff4815827c Mon Sep 17 00:00:00 2001
|
||||
From: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
Date: Wed, 16 Mar 2016 13:33:35 -0500
|
||||
Subject: rtlwifi: btcoexist: Implement antenna selection
|
||||
|
||||
The previous patch added an option to rtl8723be to manually select the
|
||||
antenna for those cases when only a single antenna is present, and the
|
||||
on-board EEPROM is incorrectly programmed. This patch implements the
|
||||
necessary changes in the Bluetooth coexistence driver.
|
||||
|
||||
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
Cc: Stable <stable@vger.kernel.org> [V4.0+]
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
.../realtek/rtlwifi/btcoexist/halbtc8723b2ant.c | 9 ++++++--
|
||||
.../realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 27 +++++++++++++++++++++-
|
||||
.../realtek/rtlwifi/btcoexist/halbtcoutsrc.h | 2 +-
|
||||
.../wireless/realtek/rtlwifi/btcoexist/rtl_btc.c | 5 +++-
|
||||
4 files changed, 38 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
|
||||
index c43ab59..77cbd10 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
|
||||
@@ -1203,7 +1203,6 @@ static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist,
|
||||
|
||||
/* Force GNT_BT to low */
|
||||
btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0);
|
||||
- btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
|
||||
|
||||
if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) {
|
||||
/* tell firmware "no antenna inverse" */
|
||||
@@ -1211,19 +1210,25 @@ static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist,
|
||||
h2c_parameter[1] = 1; /* ext switch type */
|
||||
btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
|
||||
h2c_parameter);
|
||||
+ btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
|
||||
} else {
|
||||
/* tell firmware "antenna inverse" */
|
||||
h2c_parameter[0] = 1;
|
||||
h2c_parameter[1] = 1; /* ext switch type */
|
||||
btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
|
||||
h2c_parameter);
|
||||
+ btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
|
||||
}
|
||||
}
|
||||
|
||||
/* ext switch setting */
|
||||
if (use_ext_switch) {
|
||||
/* fixed internal switch S1->WiFi, S0->BT */
|
||||
- btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
|
||||
+ if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT)
|
||||
+ btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
|
||||
+ else
|
||||
+ btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
|
||||
+
|
||||
switch (antpos_type) {
|
||||
case BTC_ANT_WIFI_AT_MAIN:
|
||||
/* ext switch main at wifi */
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
|
||||
index b2791c8..babd149 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
|
||||
@@ -965,13 +965,38 @@ void exhalbtc_set_chip_type(u8 chip_type)
|
||||
}
|
||||
}
|
||||
|
||||
-void exhalbtc_set_ant_num(u8 type, u8 ant_num)
|
||||
+void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num)
|
||||
{
|
||||
if (BT_COEX_ANT_TYPE_PG == type) {
|
||||
gl_bt_coexist.board_info.pg_ant_num = ant_num;
|
||||
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
|
||||
+ /* The antenna position:
|
||||
+ * Main (default) or Aux for pgAntNum=2 && btdmAntNum =1.
|
||||
+ * The antenna position should be determined by
|
||||
+ * auto-detect mechanism.
|
||||
+ * The following is assumed to main,
|
||||
+ * and those must be modified
|
||||
+ * if y auto-detect mechanism is ready
|
||||
+ */
|
||||
+ if ((gl_bt_coexist.board_info.pg_ant_num == 2) &&
|
||||
+ (gl_bt_coexist.board_info.btdm_ant_num == 1))
|
||||
+ gl_bt_coexist.board_info.btdm_ant_pos =
|
||||
+ BTC_ANTENNA_AT_MAIN_PORT;
|
||||
+ else
|
||||
+ gl_bt_coexist.board_info.btdm_ant_pos =
|
||||
+ BTC_ANTENNA_AT_MAIN_PORT;
|
||||
} else if (BT_COEX_ANT_TYPE_ANTDIV == type) {
|
||||
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
|
||||
+ gl_bt_coexist.board_info.btdm_ant_pos =
|
||||
+ BTC_ANTENNA_AT_MAIN_PORT;
|
||||
+ } else if (type == BT_COEX_ANT_TYPE_DETECTED) {
|
||||
+ gl_bt_coexist.board_info.btdm_ant_num = ant_num;
|
||||
+ if (rtlpriv->cfg->mod_params->ant_sel == 1)
|
||||
+ gl_bt_coexist.board_info.btdm_ant_pos =
|
||||
+ BTC_ANTENNA_AT_AUX_PORT;
|
||||
+ else
|
||||
+ gl_bt_coexist.board_info.btdm_ant_pos =
|
||||
+ BTC_ANTENNA_AT_MAIN_PORT;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
|
||||
index 0a903ea..f41ca57 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
|
||||
@@ -535,7 +535,7 @@ void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version);
|
||||
void exhalbtc_update_min_bt_rssi(char bt_rssi);
|
||||
void exhalbtc_set_bt_exist(bool bt_exist);
|
||||
void exhalbtc_set_chip_type(u8 chip_type);
|
||||
-void exhalbtc_set_ant_num(u8 type, u8 ant_num);
|
||||
+void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num);
|
||||
void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist);
|
||||
void exhalbtc_signal_compensation(struct btc_coexist *btcoexist,
|
||||
u8 *rssi_wifi, u8 *rssi_bt);
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
|
||||
index b9b0cb7..d3fd921 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
|
||||
@@ -72,7 +72,10 @@ void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
|
||||
__func__, bt_type);
|
||||
exhalbtc_set_chip_type(bt_type);
|
||||
|
||||
- exhalbtc_set_ant_num(BT_COEX_ANT_TYPE_PG, ant_num);
|
||||
+ if (rtlpriv->cfg->mod_params->ant_sel == 1)
|
||||
+ exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_DETECTED, 1);
|
||||
+ else
|
||||
+ exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num);
|
||||
}
|
||||
|
||||
void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
|
||||
--
|
||||
cgit v0.12
|
||||
|
17
kernel.spec
17
kernel.spec
|
@ -52,7 +52,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
|
||||
# Set rpm version accordingly
|
||||
%if 0%{?stable_update}
|
||||
%define stablerev %{stable_update}
|
||||
|
@ -612,9 +612,6 @@ Patch646: HID-sony-do-not-bail-out-when-the-sixaxis-refuses-th.patch
|
|||
#Known use after free, possibly rhbz 1310579
|
||||
Patch654: 0001-usb-hub-fix-panic-in-usb_reset_and_verify_device.patch
|
||||
|
||||
#Mitigates CVE-2013-4312 rhbz 1313428 1313433
|
||||
Patch659: pipe-limit-the-per-user-amount-of-pages-allocated-in.patch
|
||||
|
||||
#rhbz 1310252 1313318
|
||||
Patch660: 0001-drm-i915-Pretend-cursor-is-always-on-for-ILK-style-W.patch
|
||||
|
||||
|
@ -630,9 +627,6 @@ Patch690: x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch
|
|||
#CVE-2016-3951 rhbz 1324782 1324815
|
||||
Patch695: cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch
|
||||
|
||||
#rhbz 1309487
|
||||
Patch701: antenna_select.patch
|
||||
|
||||
# Stop splashing crap about broken firmware BGRT
|
||||
Patch704: x86-efi-bgrt-Switch-all-pr_err-to-pr_debug-for-inval.patch
|
||||
|
||||
|
@ -1332,9 +1326,6 @@ ApplyPatch HID-sony-do-not-bail-out-when-the-sixaxis-refuses-th.patch
|
|||
#Known use after free, possibly rhbz 1310579
|
||||
ApplyPatch 0001-usb-hub-fix-panic-in-usb_reset_and_verify_device.patch
|
||||
|
||||
#Mitigates CVE-2013-4312 rhbz 1313428 1313433
|
||||
ApplyPatch pipe-limit-the-per-user-amount-of-pages-allocated-in.patch
|
||||
|
||||
#rhbz 1310252 1313318
|
||||
ApplyPatch 0001-drm-i915-Pretend-cursor-is-always-on-for-ILK-style-W.patch
|
||||
|
||||
|
@ -1350,9 +1341,6 @@ ApplyPatch x86-mm-32-Enable-full-randomization-on-i386-and-X86_.patch
|
|||
#CVE-2016-3951 rhbz 1324782 1324815
|
||||
ApplyPatch cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_.patch
|
||||
|
||||
#rhbz 1309487
|
||||
ApplyPatch antenna_select.patch
|
||||
|
||||
#CVE-2016-4482 rhbz 1332931 1332932
|
||||
ApplyPatch USB-usbfs-fix-potential-infoleak-in-devio.patch
|
||||
|
||||
|
@ -2222,6 +2210,9 @@ fi
|
|||
#
|
||||
#
|
||||
%changelog
|
||||
* Wed Jun 08 2016 Laura Abbott <labbott@fedoraproject.org> - 4.4.13-200
|
||||
- Linux v4.4.13
|
||||
|
||||
* Tue Jun 07 2016 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- CVE-2016-5244 info leak in rds (rhbz 1343338 1343337)
|
||||
- CVE-2016-5243 info leak in tipc (rhbz 1343338 1343335)
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
From 759c01142a5d0f364a462346168a56de28a80f52 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Mon, 18 Jan 2016 16:36:09 +0100
|
||||
Subject: [PATCH] pipe: limit the per-user amount of pages allocated in pipes
|
||||
|
||||
On no-so-small systems, it is possible for a single process to cause an
|
||||
OOM condition by filling large pipes with data that are never read. A
|
||||
typical process filling 4000 pipes with 1 MB of data will use 4 GB of
|
||||
memory. On small systems it may be tricky to set the pipe max size to
|
||||
prevent this from happening.
|
||||
|
||||
This patch makes it possible to enforce a per-user soft limit above
|
||||
which new pipes will be limited to a single page, effectively limiting
|
||||
them to 4 kB each, as well as a hard limit above which no new pipes may
|
||||
be created for this user. This has the effect of protecting the system
|
||||
against memory abuse without hurting other users, and still allowing
|
||||
pipes to work correctly though with less data at once.
|
||||
|
||||
The limit are controlled by two new sysctls : pipe-user-pages-soft, and
|
||||
pipe-user-pages-hard. Both may be disabled by setting them to zero. The
|
||||
default soft limit allows the default number of FDs per process (1024)
|
||||
to create pipes of the default size (64kB), thus reaching a limit of 64MB
|
||||
before starting to create only smaller pipes. With 256 processes limited
|
||||
to 1024 FDs each, this results in 1024*64kB + (256*1024 - 1024) * 4kB =
|
||||
1084 MB of memory allocated for a user. The hard limit is disabled by
|
||||
default to avoid breaking existing applications that make intensive use
|
||||
of pipes (eg: for splicing).
|
||||
|
||||
Reported-by: socketpair@gmail.com
|
||||
Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
|
||||
Mitigates: CVE-2013-4312 (Linux 2.0+)
|
||||
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Willy Tarreau <w@1wt.eu>
|
||||
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
|
||||
---
|
||||
Documentation/sysctl/fs.txt | 23 ++++++++++++++++++++++
|
||||
fs/pipe.c | 47 +++++++++++++++++++++++++++++++++++++++++++--
|
||||
include/linux/pipe_fs_i.h | 4 ++++
|
||||
include/linux/sched.h | 1 +
|
||||
kernel/sysctl.c | 14 ++++++++++++++
|
||||
5 files changed, 87 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
|
||||
index 88152f214f48..302b5ed616a6 100644
|
||||
--- a/Documentation/sysctl/fs.txt
|
||||
+++ b/Documentation/sysctl/fs.txt
|
||||
@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs:
|
||||
- nr_open
|
||||
- overflowuid
|
||||
- overflowgid
|
||||
+- pipe-user-pages-hard
|
||||
+- pipe-user-pages-soft
|
||||
- protected_hardlinks
|
||||
- protected_symlinks
|
||||
- suid_dumpable
|
||||
@@ -159,6 +161,27 @@ The default is 65534.
|
||||
|
||||
==============================================================
|
||||
|
||||
+pipe-user-pages-hard:
|
||||
+
|
||||
+Maximum total number of pages a non-privileged user may allocate for pipes.
|
||||
+Once this limit is reached, no new pipes may be allocated until usage goes
|
||||
+below the limit again. When set to 0, no limit is applied, which is the default
|
||||
+setting.
|
||||
+
|
||||
+==============================================================
|
||||
+
|
||||
+pipe-user-pages-soft:
|
||||
+
|
||||
+Maximum total number of pages a non-privileged user may allocate for pipes
|
||||
+before the pipe size gets limited to a single page. Once this limit is reached,
|
||||
+new pipes will be limited to a single page in size for this user in order to
|
||||
+limit total memory usage, and trying to increase them using fcntl() will be
|
||||
+denied until usage goes below the limit again. The default value allows to
|
||||
+allocate up to 1024 pipes at their default size. When set to 0, no limit is
|
||||
+applied.
|
||||
+
|
||||
+==============================================================
|
||||
+
|
||||
protected_hardlinks:
|
||||
|
||||
A long-standing class of security issues is the hardlink-based
|
||||
diff --git a/fs/pipe.c b/fs/pipe.c
|
||||
index 42cf8ddf0e55..ab8dad3ccb6a 100644
|
||||
--- a/fs/pipe.c
|
||||
+++ b/fs/pipe.c
|
||||
@@ -38,6 +38,12 @@ unsigned int pipe_max_size = 1048576;
|
||||
*/
|
||||
unsigned int pipe_min_size = PAGE_SIZE;
|
||||
|
||||
+/* Maximum allocatable pages per user. Hard limit is unset by default, soft
|
||||
+ * matches default values.
|
||||
+ */
|
||||
+unsigned long pipe_user_pages_hard;
|
||||
+unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR;
|
||||
+
|
||||
/*
|
||||
* We use a start+len construction, which provides full use of the
|
||||
* allocated memory.
|
||||
@@ -583,20 +589,49 @@ pipe_fasync(int fd, struct file *filp, int on)
|
||||
return retval;
|
||||
}
|
||||
|
||||
+static void account_pipe_buffers(struct pipe_inode_info *pipe,
|
||||
+ unsigned long old, unsigned long new)
|
||||
+{
|
||||
+ atomic_long_add(new - old, &pipe->user->pipe_bufs);
|
||||
+}
|
||||
+
|
||||
+static bool too_many_pipe_buffers_soft(struct user_struct *user)
|
||||
+{
|
||||
+ return pipe_user_pages_soft &&
|
||||
+ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
|
||||
+}
|
||||
+
|
||||
+static bool too_many_pipe_buffers_hard(struct user_struct *user)
|
||||
+{
|
||||
+ return pipe_user_pages_hard &&
|
||||
+ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
|
||||
+}
|
||||
+
|
||||
struct pipe_inode_info *alloc_pipe_info(void)
|
||||
{
|
||||
struct pipe_inode_info *pipe;
|
||||
|
||||
pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
|
||||
if (pipe) {
|
||||
- pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL);
|
||||
+ unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
|
||||
+ struct user_struct *user = get_current_user();
|
||||
+
|
||||
+ if (!too_many_pipe_buffers_hard(user)) {
|
||||
+ if (too_many_pipe_buffers_soft(user))
|
||||
+ pipe_bufs = 1;
|
||||
+ pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
|
||||
+ }
|
||||
+
|
||||
if (pipe->bufs) {
|
||||
init_waitqueue_head(&pipe->wait);
|
||||
pipe->r_counter = pipe->w_counter = 1;
|
||||
- pipe->buffers = PIPE_DEF_BUFFERS;
|
||||
+ pipe->buffers = pipe_bufs;
|
||||
+ pipe->user = user;
|
||||
+ account_pipe_buffers(pipe, 0, pipe_bufs);
|
||||
mutex_init(&pipe->mutex);
|
||||
return pipe;
|
||||
}
|
||||
+ free_uid(user);
|
||||
kfree(pipe);
|
||||
}
|
||||
|
||||
@@ -607,6 +642,8 @@ void free_pipe_info(struct pipe_inode_info *pipe)
|
||||
{
|
||||
int i;
|
||||
|
||||
+ account_pipe_buffers(pipe, pipe->buffers, 0);
|
||||
+ free_uid(pipe->user);
|
||||
for (i = 0; i < pipe->buffers; i++) {
|
||||
struct pipe_buffer *buf = pipe->bufs + i;
|
||||
if (buf->ops)
|
||||
@@ -998,6 +1035,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
|
||||
memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
|
||||
}
|
||||
|
||||
+ account_pipe_buffers(pipe, pipe->buffers, nr_pages);
|
||||
pipe->curbuf = 0;
|
||||
kfree(pipe->bufs);
|
||||
pipe->bufs = bufs;
|
||||
@@ -1069,6 +1107,11 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
+ } else if ((too_many_pipe_buffers_hard(pipe->user) ||
|
||||
+ too_many_pipe_buffers_soft(pipe->user)) &&
|
||||
+ !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
|
||||
+ ret = -EPERM;
|
||||
+ goto out;
|
||||
}
|
||||
ret = pipe_set_size(pipe, nr_pages);
|
||||
break;
|
||||
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
|
||||
index eb8b8ac6df3c..24f5470d3944 100644
|
||||
--- a/include/linux/pipe_fs_i.h
|
||||
+++ b/include/linux/pipe_fs_i.h
|
||||
@@ -42,6 +42,7 @@ struct pipe_buffer {
|
||||
* @fasync_readers: reader side fasync
|
||||
* @fasync_writers: writer side fasync
|
||||
* @bufs: the circular array of pipe buffers
|
||||
+ * @user: the user who created this pipe
|
||||
**/
|
||||
struct pipe_inode_info {
|
||||
struct mutex mutex;
|
||||
@@ -57,6 +58,7 @@ struct pipe_inode_info {
|
||||
struct fasync_struct *fasync_readers;
|
||||
struct fasync_struct *fasync_writers;
|
||||
struct pipe_buffer *bufs;
|
||||
+ struct user_struct *user;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -123,6 +125,8 @@ void pipe_unlock(struct pipe_inode_info *);
|
||||
void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
|
||||
|
||||
extern unsigned int pipe_max_size, pipe_min_size;
|
||||
+extern unsigned long pipe_user_pages_hard;
|
||||
+extern unsigned long pipe_user_pages_soft;
|
||||
int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
|
||||
|
||||
|
||||
diff --git a/include/linux/sched.h b/include/linux/sched.h
|
||||
index 61aa9bbea871..1589ddc88e38 100644
|
||||
--- a/include/linux/sched.h
|
||||
+++ b/include/linux/sched.h
|
||||
@@ -835,6 +835,7 @@ struct user_struct {
|
||||
#endif
|
||||
unsigned long locked_shm; /* How many pages of mlocked shm ? */
|
||||
unsigned long unix_inflight; /* How many files in flight in unix sockets */
|
||||
+ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */
|
||||
|
||||
#ifdef CONFIG_KEYS
|
||||
struct key *uid_keyring; /* UID specific keyring */
|
||||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
|
||||
index c810f8afdb7f..f6fd236429bd 100644
|
||||
--- a/kernel/sysctl.c
|
||||
+++ b/kernel/sysctl.c
|
||||
@@ -1757,6 +1757,20 @@ static struct ctl_table fs_table[] = {
|
||||
.proc_handler = &pipe_proc_fn,
|
||||
.extra1 = &pipe_min_size,
|
||||
},
|
||||
+ {
|
||||
+ .procname = "pipe-user-pages-hard",
|
||||
+ .data = &pipe_user_pages_hard,
|
||||
+ .maxlen = sizeof(pipe_user_pages_hard),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = proc_doulongvec_minmax,
|
||||
+ },
|
||||
+ {
|
||||
+ .procname = "pipe-user-pages-soft",
|
||||
+ .data = &pipe_user_pages_soft,
|
||||
+ .maxlen = sizeof(pipe_user_pages_soft),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = proc_doulongvec_minmax,
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
|
||||
--
|
||||
2.5.0
|
||||
|
Loading…
Reference in New Issue