未验证 提交 61798d1a 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!456 Backport CVEs and bugfixes

Merge Pull Request from: @zhangjialin11 
 
Pull new CVEs:
CVE-2023-1118
CVE-2023-1073
CVE-2022-27672
CVE-2023-0461
CVE-2023-1075
CVE-2023-22995
CVE-2023-26607
CVE-2023-1078
CVE-2023-1076

net bugfix from Zhang Changzhong
md bugfixes from Yu Kuai
blk-mq bugfix from Yu Kuai
fs bugfixes from Baokun Li and Zhihao Cheng
ring-buffer bugfix from Zheng Yejian 
 
Link:https://gitee.com/openeuler/kernel/pulls/456 

Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> 
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> 
.. SPDX-License-Identifier: GPL-2.0
Cross-Thread Return Address Predictions
=======================================
Certain AMD and Hygon processors are subject to a cross-thread return address
predictions vulnerability. When running in SMT mode and one sibling thread
transitions out of C0 state, the other sibling thread could use return target
predictions from the sibling thread that transitioned out of C0.
The Spectre v2 mitigations protect the Linux kernel, as it fills the return
address prediction entries with safe targets when context switching to the idle
thread. However, KVM does allow a VMM to prevent exiting guest mode when
transitioning out of C0. This could result in a guest-controlled return target
being consumed by the sibling thread.
Affected processors
-------------------
The following CPUs are vulnerable:
- AMD Family 17h processors
- Hygon Family 18h processors
Related CVEs
------------
The following CVE entry is related to this issue:
============== =======================================
CVE-2022-27672 Cross-Thread Return Address Predictions
============== =======================================
Problem
-------
Affected SMT-capable processors support 1T and 2T modes of execution when SMT
is enabled. In 2T mode, both threads in a core are executing code. For the
processor core to enter 1T mode, it is required that one of the threads
requests to transition out of the C0 state. This can be communicated with the
HLT instruction or with an MWAIT instruction that requests non-C0.
When the thread re-enters the C0 state, the processor transitions back
to 2T mode, assuming the other thread is also still in C0 state.
In affected processors, the return address predictor (RAP) is partitioned
depending on the SMT mode. For instance, in 2T mode each thread uses a private
16-entry RAP, but in 1T mode, the active thread uses a 32-entry RAP. Upon
transition between 1T/2T mode, the RAP contents are not modified but the RAP
pointers (which control the next return target to use for predictions) may
change. This behavior may result in return targets from one SMT thread being
used by RET predictions in the sibling thread following a 1T/2T switch. In
particular, a RET instruction executed immediately after a transition to 1T may
use a return target from the thread that just became idle. In theory, this
could lead to information disclosure if the return targets used do not come
from trustworthy code.
Attack scenarios
----------------
An attack can be mounted on affected processors by performing a series of CALL
instructions with targeted return locations and then transitioning out of C0
state.
Mitigation mechanism
--------------------
Before entering idle state, the kernel context switches to the idle thread. The
context switch fills the RAP entries (referred to as the RSB in Linux) with safe
targets by performing a sequence of CALL instructions.
Prevent a guest VM from directly putting the processor into an idle state by
intercepting HLT and MWAIT instructions.
Both mitigations are required to fully address this issue.
Mitigation control on the kernel command line
---------------------------------------------
Use existing Spectre v2 mitigations that will fill the RSB on context switch.
Mitigation control for KVM - module parameter
---------------------------------------------
By default, the KVM hypervisor mitigates this issue by intercepting guest
attempts to transition out of C0. A VMM can use the KVM_CAP_X86_DISABLE_EXITS
capability to override those interceptions, but since this is not common, the
mitigation that covers this path is not enabled by default.
The mitigation for the KVM_CAP_X86_DISABLE_EXITS capability can be turned on
using the boolean module parameter mitigate_smt_rsb, e.g. ``kvm.mitigate_smt_rsb=1``.
...@@ -17,3 +17,4 @@ are configurable at compile, boot or run time. ...@@ -17,3 +17,4 @@ are configurable at compile, boot or run time.
special-register-buffer-data-sampling.rst special-register-buffer-data-sampling.rst
core-scheduling.rst core-scheduling.rst
processor_mmio_stale_data.rst processor_mmio_stale_data.rst
cross-thread-rsb.rst
...@@ -471,5 +471,6 @@ ...@@ -471,5 +471,6 @@
#define X86_BUG_MMIO_UNKNOWN X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */ #define X86_BUG_MMIO_UNKNOWN X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */
#define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */ #define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */
#define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */ #define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
#define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */
#endif /* _ASM_X86_CPUFEATURES_H */ #endif /* _ASM_X86_CPUFEATURES_H */
...@@ -1124,6 +1124,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { ...@@ -1124,6 +1124,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
#define MMIO_SBDS BIT(2) #define MMIO_SBDS BIT(2)
/* CPU is affected by RETbleed, speculating where you would not expect it */ /* CPU is affected by RETbleed, speculating where you would not expect it */
#define RETBLEED BIT(3) #define RETBLEED BIT(3)
/* CPU is affected by SMT (cross-thread) return predictions */
#define SMT_RSB BIT(4)
static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS), VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS),
...@@ -1155,8 +1157,8 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { ...@@ -1155,8 +1157,8 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
VULNBL_AMD(0x15, RETBLEED), VULNBL_AMD(0x15, RETBLEED),
VULNBL_AMD(0x16, RETBLEED), VULNBL_AMD(0x16, RETBLEED),
VULNBL_AMD(0x17, RETBLEED), VULNBL_AMD(0x17, RETBLEED | SMT_RSB),
VULNBL_HYGON(0x18, RETBLEED), VULNBL_HYGON(0x18, RETBLEED | SMT_RSB),
{} {}
}; };
...@@ -1274,6 +1276,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) ...@@ -1274,6 +1276,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
!(ia32_cap & ARCH_CAP_PBRSB_NO)) !(ia32_cap & ARCH_CAP_PBRSB_NO))
setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB); setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
if (cpu_matches(cpu_vuln_blacklist, SMT_RSB))
setup_force_cpu_bug(X86_BUG_SMT_RSB);
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
return; return;
......
...@@ -174,6 +174,10 @@ module_param(force_emulation_prefix, bool, S_IRUGO); ...@@ -174,6 +174,10 @@ module_param(force_emulation_prefix, bool, S_IRUGO);
int __read_mostly pi_inject_timer = -1; int __read_mostly pi_inject_timer = -1;
module_param(pi_inject_timer, bint, S_IRUGO | S_IWUSR); module_param(pi_inject_timer, bint, S_IRUGO | S_IWUSR);
/* Enable/disable SMT_RSB bug mitigation */
bool __read_mostly mitigate_smt_rsb;
module_param(mitigate_smt_rsb, bool, 0444);
/* /*
* Restoring the host value for MSRs that are only consumed when running in * Restoring the host value for MSRs that are only consumed when running in
* usermode, e.g. SYSCALL MSRs and TSC_AUX, can be deferred until the CPU * usermode, e.g. SYSCALL MSRs and TSC_AUX, can be deferred until the CPU
...@@ -3945,10 +3949,15 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) ...@@ -3945,10 +3949,15 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = KVM_CLOCK_TSC_STABLE; r = KVM_CLOCK_TSC_STABLE;
break; break;
case KVM_CAP_X86_DISABLE_EXITS: case KVM_CAP_X86_DISABLE_EXITS:
r |= KVM_X86_DISABLE_EXITS_HLT | KVM_X86_DISABLE_EXITS_PAUSE | r = KVM_X86_DISABLE_EXITS_PAUSE;
KVM_X86_DISABLE_EXITS_CSTATE;
if(kvm_can_mwait_in_guest()) if (!mitigate_smt_rsb) {
r |= KVM_X86_DISABLE_EXITS_MWAIT; r |= KVM_X86_DISABLE_EXITS_HLT |
KVM_X86_DISABLE_EXITS_CSTATE;
if (kvm_can_mwait_in_guest())
r |= KVM_X86_DISABLE_EXITS_MWAIT;
}
break; break;
case KVM_CAP_X86_SMM: case KVM_CAP_X86_SMM:
/* SMBASE is usually relocated above 1M on modern chipsets, /* SMBASE is usually relocated above 1M on modern chipsets,
...@@ -5491,15 +5500,26 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, ...@@ -5491,15 +5500,26 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
if (cap->args[0] & ~KVM_X86_DISABLE_VALID_EXITS) if (cap->args[0] & ~KVM_X86_DISABLE_VALID_EXITS)
break; break;
if ((cap->args[0] & KVM_X86_DISABLE_EXITS_MWAIT) &&
kvm_can_mwait_in_guest())
kvm->arch.mwait_in_guest = true;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_HLT)
kvm->arch.hlt_in_guest = true;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_PAUSE) if (cap->args[0] & KVM_X86_DISABLE_EXITS_PAUSE)
kvm->arch.pause_in_guest = true; kvm->arch.pause_in_guest = true;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_CSTATE)
kvm->arch.cstate_in_guest = true; #define SMT_RSB_MSG "This processor is affected by the Cross-Thread Return Predictions vulnerability. " \
"KVM_CAP_X86_DISABLE_EXITS should only be used with SMT disabled or trusted guests."
if (!mitigate_smt_rsb) {
if (boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible() &&
(cap->args[0] & ~KVM_X86_DISABLE_EXITS_PAUSE))
pr_warn_once(SMT_RSB_MSG);
if ((cap->args[0] & KVM_X86_DISABLE_EXITS_MWAIT) &&
kvm_can_mwait_in_guest())
kvm->arch.mwait_in_guest = true;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_HLT)
kvm->arch.hlt_in_guest = true;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_CSTATE)
kvm->arch.cstate_in_guest = true;
}
r = 0; r = 0;
break; break;
case KVM_CAP_MSR_PLATFORM_INFO: case KVM_CAP_MSR_PLATFORM_INFO:
...@@ -11698,6 +11718,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_apicv_update_request); ...@@ -11698,6 +11718,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_apicv_update_request);
static int __init kvm_x86_init(void) static int __init kvm_x86_init(void)
{ {
kvm_mmu_x86_module_init(); kvm_mmu_x86_module_init();
mitigate_smt_rsb &= boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible();
return 0; return 0;
} }
module_init(kvm_x86_init); module_init(kvm_x86_init);
......
...@@ -3873,14 +3873,14 @@ static bool blk_mq_elv_switch_none(struct list_head *head, ...@@ -3873,14 +3873,14 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
mutex_lock(&q->sysfs_lock); mutex_lock(&q->sysfs_lock);
/* /*
* After elevator_switch_mq, the previous elevator_queue will be * After elevator_switch, the previous elevator_queue will be
* released by elevator_release. The reference of the io scheduler * released by elevator_release. The reference of the io scheduler
* module get by elevator_get will also be put. So we need to get * module get by elevator_get will also be put. So we need to get
* a reference of the io scheduler module here to prevent it to be * a reference of the io scheduler module here to prevent it to be
* removed. * removed.
*/ */
__module_get(qe->type->elevator_owner); __module_get(qe->type->elevator_owner);
elevator_switch_mq(q, NULL); elevator_switch(q, NULL);
mutex_unlock(&q->sysfs_lock); mutex_unlock(&q->sysfs_lock);
return true; return true;
...@@ -3905,7 +3905,7 @@ static void blk_mq_elv_switch_back(struct list_head *head, ...@@ -3905,7 +3905,7 @@ static void blk_mq_elv_switch_back(struct list_head *head,
kfree(qe); kfree(qe);
mutex_lock(&q->sysfs_lock); mutex_lock(&q->sysfs_lock);
elevator_switch_mq(q, t); elevator_switch(q, t);
mutex_unlock(&q->sysfs_lock); mutex_unlock(&q->sysfs_lock);
} }
......
...@@ -201,8 +201,7 @@ void blk_account_io_done(struct request *req, u64 now); ...@@ -201,8 +201,7 @@ void blk_account_io_done(struct request *req, u64 now);
void blk_insert_flush(struct request *rq); void blk_insert_flush(struct request *rq);
void elevator_init_mq(struct request_queue *q); void elevator_init_mq(struct request_queue *q);
int elevator_switch_mq(struct request_queue *q, int elevator_switch(struct request_queue *q, struct elevator_type *new_e);
struct elevator_type *new_e);
void __elevator_exit(struct request_queue *, struct elevator_queue *); void __elevator_exit(struct request_queue *, struct elevator_queue *);
int elv_register_queue(struct request_queue *q, bool uevent); int elv_register_queue(struct request_queue *q, bool uevent);
void elv_unregister_queue(struct request_queue *q); void elv_unregister_queue(struct request_queue *q);
......
...@@ -577,7 +577,7 @@ void elv_unregister(struct elevator_type *e) ...@@ -577,7 +577,7 @@ void elv_unregister(struct elevator_type *e)
} }
EXPORT_SYMBOL_GPL(elv_unregister); EXPORT_SYMBOL_GPL(elv_unregister);
int elevator_switch_mq(struct request_queue *q, static int elevator_switch_mq(struct request_queue *q,
struct elevator_type *new_e) struct elevator_type *new_e)
{ {
int ret; int ret;
...@@ -716,7 +716,7 @@ void elevator_init_mq(struct request_queue *q) ...@@ -716,7 +716,7 @@ void elevator_init_mq(struct request_queue *q)
* need for the new one. this way we have a chance of going back to the old * need for the new one. this way we have a chance of going back to the old
* one, if the new one fails init for some reason. * one, if the new one fails init for some reason.
*/ */
static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
{ {
int err; int err;
......
...@@ -344,6 +344,11 @@ static int bigben_probe(struct hid_device *hid, ...@@ -344,6 +344,11 @@ static int bigben_probe(struct hid_device *hid,
} }
report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
if (list_empty(report_list)) {
hid_err(hid, "no output report found\n");
error = -ENODEV;
goto error_hw_stop;
}
bigben->report = list_entry(report_list->next, bigben->report = list_entry(report_list->next,
struct hid_report, list); struct hid_report, list);
......
...@@ -988,8 +988,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid, ...@@ -988,8 +988,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
* Validating on id 0 means we should examine the first * Validating on id 0 means we should examine the first
* report in the list. * report in the list.
*/ */
report = list_entry( report = list_first_entry_or_null(
hid->report_enum[type].report_list.next, &hid->report_enum[type].report_list,
struct hid_report, list); struct hid_report, list);
} else { } else {
report = hid->report_enum[type].report_id_hash[id]; report = hid->report_enum[type].report_id_hash[id];
......
...@@ -5043,7 +5043,7 @@ static ssize_t ...@@ -5043,7 +5043,7 @@ static ssize_t
sync_speed_show(struct mddev *mddev, char *page) sync_speed_show(struct mddev *mddev, char *page)
{ {
unsigned long resync, dt, db; unsigned long resync, dt, db;
if (mddev->curr_resync == 0) if (mddev->curr_resync == MD_RESYNC_NONE)
return sprintf(page, "none\n"); return sprintf(page, "none\n");
resync = mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active); resync = mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active);
dt = (jiffies - mddev->resync_mark) / HZ; dt = (jiffies - mddev->resync_mark) / HZ;
...@@ -5062,8 +5062,8 @@ sync_completed_show(struct mddev *mddev, char *page) ...@@ -5062,8 +5062,8 @@ sync_completed_show(struct mddev *mddev, char *page)
if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
return sprintf(page, "none\n"); return sprintf(page, "none\n");
if (mddev->curr_resync == 1 || if (mddev->curr_resync == MD_RESYNC_YIELDED ||
mddev->curr_resync == 2) mddev->curr_resync == MD_RESYNC_DELAYED)
return sprintf(page, "delayed\n"); return sprintf(page, "delayed\n");
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) || if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
...@@ -8069,16 +8069,26 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev) ...@@ -8069,16 +8069,26 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev)
max_sectors = mddev->dev_sectors; max_sectors = mddev->dev_sectors;
resync = mddev->curr_resync; resync = mddev->curr_resync;
if (resync <= 3) { if (resync < MD_RESYNC_ACTIVE) {
if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
/* Still cleaning up */ /* Still cleaning up */
resync = max_sectors; resync = max_sectors;
} else if (resync > max_sectors) } else if (resync > max_sectors) {
resync = max_sectors; resync = max_sectors;
else } else {
resync -= atomic_read(&mddev->recovery_active); res = atomic_read(&mddev->recovery_active);
/*
* Resync has started, but the subtraction has overflowed or
* yielded one of the special values. Force it to active to
* ensure the status reports an active resync.
*/
if (resync < res || resync - res < MD_RESYNC_ACTIVE)
resync = MD_RESYNC_ACTIVE;
else
resync -= res;
}
if (resync == 0) { if (resync == MD_RESYNC_NONE) {
if (test_bit(MD_RESYNCING_REMOTE, &mddev->recovery)) { if (test_bit(MD_RESYNCING_REMOTE, &mddev->recovery)) {
struct md_rdev *rdev; struct md_rdev *rdev;
...@@ -8102,7 +8112,7 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev) ...@@ -8102,7 +8112,7 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev)
} }
return 0; return 0;
} }
if (resync < 3) { if (resync < MD_RESYNC_ACTIVE) {
seq_printf(seq, "\tresync=DELAYED"); seq_printf(seq, "\tresync=DELAYED");
return 1; return 1;
} }
...@@ -8740,13 +8750,7 @@ void md_do_sync(struct md_thread *thread) ...@@ -8740,13 +8750,7 @@ void md_do_sync(struct md_thread *thread)
mddev->last_sync_action = action ?: desc; mddev->last_sync_action = action ?: desc;
/* we overload curr_resync somewhat here. /*
* 0 == not engaged in resync at all
* 2 == checking that there is no conflict with another sync
* 1 == like 2, but have yielded to allow conflicting resync to
* commence
* other == active in resync - this many blocks
*
* Before starting a resync we must have set curr_resync to * Before starting a resync we must have set curr_resync to
* 2, and then checked that every "conflicting" array has curr_resync * 2, and then checked that every "conflicting" array has curr_resync
* less than ours. When we find one that is the same or higher * less than ours. When we find one that is the same or higher
...@@ -8758,7 +8762,7 @@ void md_do_sync(struct md_thread *thread) ...@@ -8758,7 +8762,7 @@ void md_do_sync(struct md_thread *thread)
do { do {
int mddev2_minor = -1; int mddev2_minor = -1;
mddev->curr_resync = 2; mddev->curr_resync = MD_RESYNC_DELAYED;
try_again: try_again:
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
...@@ -8770,12 +8774,14 @@ void md_do_sync(struct md_thread *thread) ...@@ -8770,12 +8774,14 @@ void md_do_sync(struct md_thread *thread)
&& mddev2->curr_resync && mddev2->curr_resync
&& match_mddev_units(mddev, mddev2)) { && match_mddev_units(mddev, mddev2)) {
DEFINE_WAIT(wq); DEFINE_WAIT(wq);
if (mddev < mddev2 && mddev->curr_resync == 2) { if (mddev < mddev2 &&
mddev->curr_resync == MD_RESYNC_DELAYED) {
/* arbitrarily yield */ /* arbitrarily yield */
mddev->curr_resync = 1; mddev->curr_resync = MD_RESYNC_YIELDED;
wake_up(&resync_wait); wake_up(&resync_wait);
} }
if (mddev > mddev2 && mddev->curr_resync == 1) if (mddev > mddev2 &&
mddev->curr_resync == MD_RESYNC_YIELDED)
/* no need to wait here, we can wait the next /* no need to wait here, we can wait the next
* time 'round when curr_resync == 2 * time 'round when curr_resync == 2
*/ */
...@@ -8803,7 +8809,7 @@ void md_do_sync(struct md_thread *thread) ...@@ -8803,7 +8809,7 @@ void md_do_sync(struct md_thread *thread)
finish_wait(&resync_wait, &wq); finish_wait(&resync_wait, &wq);
} }
} }
} while (mddev->curr_resync < 2); } while (mddev->curr_resync < MD_RESYNC_DELAYED);
j = 0; j = 0;
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
...@@ -8887,7 +8893,7 @@ void md_do_sync(struct md_thread *thread) ...@@ -8887,7 +8893,7 @@ void md_do_sync(struct md_thread *thread)
desc, mdname(mddev)); desc, mdname(mddev));
mddev->curr_resync = j; mddev->curr_resync = j;
} else } else
mddev->curr_resync = 3; /* no longer delayed */ mddev->curr_resync = MD_RESYNC_ACTIVE; /* no longer delayed */
mddev->curr_resync_completed = j; mddev->curr_resync_completed = j;
sysfs_notify_dirent_safe(mddev->sysfs_completed); sysfs_notify_dirent_safe(mddev->sysfs_completed);
md_new_event(mddev); md_new_event(mddev);
...@@ -9022,14 +9028,14 @@ void md_do_sync(struct md_thread *thread) ...@@ -9022,14 +9028,14 @@ void md_do_sync(struct md_thread *thread)
if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && !test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
mddev->curr_resync > 3) { mddev->curr_resync >= MD_RESYNC_ACTIVE) {
mddev->curr_resync_completed = mddev->curr_resync; mddev->curr_resync_completed = mddev->curr_resync;
sysfs_notify_dirent_safe(mddev->sysfs_completed); sysfs_notify_dirent_safe(mddev->sysfs_completed);
} }
mddev->pers->sync_request(mddev, max_sectors, &skipped); mddev->pers->sync_request(mddev, max_sectors, &skipped);
if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
mddev->curr_resync > 3) { mddev->curr_resync > MD_RESYNC_ACTIVE) {
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
if (mddev->curr_resync >= mddev->recovery_cp) { if (mddev->curr_resync >= mddev->recovery_cp) {
...@@ -9094,7 +9100,7 @@ void md_do_sync(struct md_thread *thread) ...@@ -9094,7 +9100,7 @@ void md_do_sync(struct md_thread *thread)
} else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) } else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
mddev->resync_min = mddev->curr_resync_completed; mddev->resync_min = mddev->curr_resync_completed;
set_bit(MD_RECOVERY_DONE, &mddev->recovery); set_bit(MD_RECOVERY_DONE, &mddev->recovery);
mddev->curr_resync = 0; mddev->curr_resync = MD_RESYNC_NONE;
spin_unlock(&mddev->lock); spin_unlock(&mddev->lock);
wake_up(&resync_wait); wake_up(&resync_wait);
......
...@@ -284,6 +284,21 @@ struct serial_info { ...@@ -284,6 +284,21 @@ struct serial_info {
sector_t _subtree_last; /* highest sector in subtree of rb node */ sector_t _subtree_last; /* highest sector in subtree of rb node */
}; };
/*
* mddev->curr_resync stores the current sector of the resync but
* also has some overloaded values.
*/
enum {
/* No resync in progress */
MD_RESYNC_NONE = 0,
/* Yielded to allow another conflicting resync to commence */
MD_RESYNC_YIELDED = 1,
/* Delayed to check that there is no conflict with another sync */
MD_RESYNC_DELAYED = 2,
/* Any value greater than or equal to this is in an active resync */
MD_RESYNC_ACTIVE = 3,
};
struct mddev { struct mddev {
void *private; void *private;
struct md_personality *pers; struct md_personality *pers;
......
...@@ -1117,7 +1117,7 @@ static void regular_request_wait(struct mddev *mddev, struct r10conf *conf, ...@@ -1117,7 +1117,7 @@ static void regular_request_wait(struct mddev *mddev, struct r10conf *conf,
} }
static void raid10_read_request(struct mddev *mddev, struct bio *bio, static void raid10_read_request(struct mddev *mddev, struct bio *bio,
struct r10bio *r10_bio) struct r10bio *r10_bio, bool handle_error)
{ {
struct r10conf *conf = mddev->private; struct r10conf *conf = mddev->private;
struct bio *read_bio; struct bio *read_bio;
...@@ -1187,7 +1187,7 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, ...@@ -1187,7 +1187,7 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
} }
slot = r10_bio->read_slot; slot = r10_bio->read_slot;
if (blk_queue_io_stat(bio->bi_disk->queue)) if (!handle_error && blk_queue_io_stat(bio->bi_disk->queue))
r10_bio->start_time = bio_start_io_acct(bio); r10_bio->start_time = bio_start_io_acct(bio);
read_bio = bio_clone_fast(bio, gfp, &mddev->bio_set); read_bio = bio_clone_fast(bio, gfp, &mddev->bio_set);
...@@ -1503,7 +1503,7 @@ static void __make_request(struct mddev *mddev, struct bio *bio, int sectors) ...@@ -1503,7 +1503,7 @@ static void __make_request(struct mddev *mddev, struct bio *bio, int sectors)
memset(r10_bio->devs, 0, sizeof(r10_bio->devs[0]) * conf->copies); memset(r10_bio->devs, 0, sizeof(r10_bio->devs[0]) * conf->copies);
if (bio_data_dir(bio) == READ) if (bio_data_dir(bio) == READ)
raid10_read_request(mddev, bio, r10_bio); raid10_read_request(mddev, bio, r10_bio, false);
else else
raid10_write_request(mddev, bio, r10_bio); raid10_write_request(mddev, bio, r10_bio);
} }
...@@ -2218,11 +2218,22 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio) ...@@ -2218,11 +2218,22 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
{ {
struct r10conf *conf = mddev->private; struct r10conf *conf = mddev->private;
int d; int d;
struct bio *wbio, *wbio2; struct bio *wbio = r10_bio->devs[1].bio;
struct bio *wbio2 = r10_bio->devs[1].repl_bio;
/* Need to test wbio2->bi_end_io before we call
* submit_bio_noacct as if the former is NULL,
* the latter is free to free wbio2.
*/
if (wbio2 && !wbio2->bi_end_io)
wbio2 = NULL;
if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) { if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) {
fix_recovery_read_error(r10_bio); fix_recovery_read_error(r10_bio);
end_sync_request(r10_bio); if (wbio->bi_end_io)
end_sync_request(r10_bio);
if (wbio2)
end_sync_request(r10_bio);
return; return;
} }
...@@ -2231,14 +2242,6 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio) ...@@ -2231,14 +2242,6 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
* and submit the write request * and submit the write request
*/ */
d = r10_bio->devs[1].devnum; d = r10_bio->devs[1].devnum;
wbio = r10_bio->devs[1].bio;
wbio2 = r10_bio->devs[1].repl_bio;
/* Need to test wbio2->bi_end_io before we call
* submit_bio_noacct as if the former is NULL,
* the latter is free to free wbio2.
*/
if (wbio2 && !wbio2->bi_end_io)
wbio2 = NULL;
if (wbio->bi_end_io) { if (wbio->bi_end_io) {
atomic_inc(&conf->mirrors[d].rdev->nr_pending); atomic_inc(&conf->mirrors[d].rdev->nr_pending);
md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(wbio)); md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(wbio));
...@@ -2597,7 +2600,7 @@ static void handle_read_error(struct mddev *mddev, struct r10bio *r10_bio) ...@@ -2597,7 +2600,7 @@ static void handle_read_error(struct mddev *mddev, struct r10bio *r10_bio)
rdev_dec_pending(rdev, mddev); rdev_dec_pending(rdev, mddev);
allow_barrier(conf); allow_barrier(conf);
r10_bio->state = 0; r10_bio->state = 0;
raid10_read_request(mddev, r10_bio->master_bio, r10_bio); raid10_read_request(mddev, r10_bio->master_bio, r10_bio, true);
} }
static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio) static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
......
...@@ -1106,6 +1106,8 @@ static void ene_remove(struct pnp_dev *pnp_dev) ...@@ -1106,6 +1106,8 @@ static void ene_remove(struct pnp_dev *pnp_dev)
struct ene_device *dev = pnp_get_drvdata(pnp_dev); struct ene_device *dev = pnp_get_drvdata(pnp_dev);
unsigned long flags; unsigned long flags;
rc_unregister_device(dev->rdev);
del_timer_sync(&dev->tx_sim_timer);
spin_lock_irqsave(&dev->hw_lock, flags); spin_lock_irqsave(&dev->hw_lock, flags);
ene_rx_disable(dev); ene_rx_disable(dev);
ene_rx_restore_hw_buffer(dev); ene_rx_restore_hw_buffer(dev);
...@@ -1113,7 +1115,6 @@ static void ene_remove(struct pnp_dev *pnp_dev) ...@@ -1113,7 +1115,6 @@ static void ene_remove(struct pnp_dev *pnp_dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
release_region(dev->hw_io, ENE_IO_SIZE); release_region(dev->hw_io, ENE_IO_SIZE);
rc_unregister_device(dev->rdev);
kfree(dev); kfree(dev);
} }
......
...@@ -523,7 +523,7 @@ static int tap_open(struct inode *inode, struct file *file) ...@@ -523,7 +523,7 @@ static int tap_open(struct inode *inode, struct file *file)
q->sock.state = SS_CONNECTED; q->sock.state = SS_CONNECTED;
q->sock.file = file; q->sock.file = file;
q->sock.ops = &tap_socket_ops; q->sock.ops = &tap_socket_ops;
sock_init_data(&q->sock, &q->sk); sock_init_data_uid(&q->sock, &q->sk, inode->i_uid);
q->sk.sk_write_space = tap_sock_write_space; q->sk.sk_write_space = tap_sock_write_space;
q->sk.sk_destruct = tap_sock_destruct; q->sk.sk_destruct = tap_sock_destruct;
q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
......
...@@ -3446,7 +3446,7 @@ static int tun_chr_open(struct inode *inode, struct file * file) ...@@ -3446,7 +3446,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
tfile->socket.file = file; tfile->socket.file = file;
tfile->socket.ops = &tun_socket_ops; tfile->socket.ops = &tun_socket_ops;
sock_init_data(&tfile->socket, &tfile->sk); sock_init_data_uid(&tfile->socket, &tfile->sk, inode->i_uid);
tfile->sk.sk_write_space = tun_sock_write_space; tfile->sk.sk_write_space = tun_sock_write_space;
tfile->sk.sk_sndbuf = INT_MAX; tfile->sk.sk_sndbuf = INT_MAX;
......
...@@ -606,8 +606,10 @@ static int dwc3_qcom_acpi_register_core(struct platform_device *pdev) ...@@ -606,8 +606,10 @@ static int dwc3_qcom_acpi_register_core(struct platform_device *pdev)
qcom->dwc3->dev.coherent_dma_mask = dev->coherent_dma_mask; qcom->dwc3->dev.coherent_dma_mask = dev->coherent_dma_mask;
child_res = kcalloc(2, sizeof(*child_res), GFP_KERNEL); child_res = kcalloc(2, sizeof(*child_res), GFP_KERNEL);
if (!child_res) if (!child_res) {
platform_device_put(qcom->dwc3);
return -ENOMEM; return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
...@@ -643,10 +645,15 @@ static int dwc3_qcom_acpi_register_core(struct platform_device *pdev) ...@@ -643,10 +645,15 @@ static int dwc3_qcom_acpi_register_core(struct platform_device *pdev)
} }
ret = platform_device_add(qcom->dwc3); ret = platform_device_add(qcom->dwc3);
if (ret) if (ret) {
dev_err(&pdev->dev, "failed to add device\n"); dev_err(&pdev->dev, "failed to add device\n");
goto out;
}
kfree(child_res);
return 0;
out: out:
platform_device_put(qcom->dwc3);
kfree(child_res); kfree(child_res);
return ret; return ret;
} }
......
...@@ -594,11 +594,23 @@ static int ntfs_attr_find(const ATTR_TYPE type, const ntfschar *name, ...@@ -594,11 +594,23 @@ static int ntfs_attr_find(const ATTR_TYPE type, const ntfschar *name,
for (;; a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length))) { for (;; a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length))) {
u8 *mrec_end = (u8 *)ctx->mrec + u8 *mrec_end = (u8 *)ctx->mrec +
le32_to_cpu(ctx->mrec->bytes_allocated); le32_to_cpu(ctx->mrec->bytes_allocated);
u8 *name_end = (u8 *)a + le16_to_cpu(a->name_offset) + u8 *name_end;
a->name_length * sizeof(ntfschar);
if ((u8*)a < (u8*)ctx->mrec || (u8*)a > mrec_end || /* check whether ATTR_RECORD wrap */
name_end > mrec_end) if ((u8 *)a < (u8 *)ctx->mrec)
break;
/* check whether Attribute Record Header is within bounds */
if ((u8 *)a > mrec_end ||
(u8 *)a + sizeof(ATTR_RECORD) > mrec_end)
break; break;
/* check whether ATTR_RECORD's name is within bounds */
name_end = (u8 *)a + le16_to_cpu(a->name_offset) +
a->name_length * sizeof(ntfschar);
if (name_end > mrec_end)
break;
ctx->attr = a; ctx->attr = a;
if (unlikely(le32_to_cpu(a->type) > le32_to_cpu(type) || if (unlikely(le32_to_cpu(a->type) > le32_to_cpu(type) ||
a->type == AT_END)) a->type == AT_END))
......
...@@ -138,11 +138,16 @@ static int ovl_dentry_revalidate_common(struct dentry *dentry, ...@@ -138,11 +138,16 @@ static int ovl_dentry_revalidate_common(struct dentry *dentry,
unsigned int flags, bool weak) unsigned int flags, bool weak)
{ {
struct ovl_entry *oe = dentry->d_fsdata; struct ovl_entry *oe = dentry->d_fsdata;
struct inode *inode = d_inode_rcu(dentry);
struct dentry *upper; struct dentry *upper;
unsigned int i; unsigned int i;
int ret = 1; int ret = 1;
upper = ovl_dentry_upper(dentry); /* Careful in RCU mode */
if (!inode)
return -ECHILD;
upper = ovl_i_dentry_upper(inode);
if (upper) if (upper)
ret = ovl_revalidate_real(upper, flags, weak); ret = ovl_revalidate_real(upper, flags, weak);
......
...@@ -662,12 +662,14 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ...@@ -662,12 +662,14 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
/* build the vector */ /* build the vector */
left = sd.total_len; left = sd.total_len;
for (n = 0; !pipe_empty(head, tail) && left && n < nbufs; tail++, n++) { for (n = 0; !pipe_empty(head, tail) && left && n < nbufs; tail++) {
struct pipe_buffer *buf = &pipe->bufs[tail & mask]; struct pipe_buffer *buf = &pipe->bufs[tail & mask];
size_t this_len = buf->len; size_t this_len = buf->len;
if (this_len > left) /* zero-length bvecs are not supported, skip them */
this_len = left; if (!this_len)
continue;
this_len = min(this_len, left);
ret = pipe_buf_confirm(pipe, buf); ret = pipe_buf_confirm(pipe, buf);
if (unlikely(ret)) { if (unlikely(ret)) {
...@@ -680,6 +682,7 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ...@@ -680,6 +682,7 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
array[n].bv_len = this_len; array[n].bv_len = this_len;
array[n].bv_offset = buf->offset; array[n].bv_offset = buf->offset;
left -= this_len; left -= this_len;
n++;
} }
iov_iter_bvec(&from, WRITE, array, n, sd.total_len - left); iov_iter_bvec(&from, WRITE, array, n, sd.total_len - left);
......
...@@ -1808,7 +1808,12 @@ void sk_common_release(struct sock *sk); ...@@ -1808,7 +1808,12 @@ void sk_common_release(struct sock *sk);
* Default socket callbacks and setup code * Default socket callbacks and setup code
*/ */
/* Initialise core socket variables */ /* Initialise core socket variables using an explicit uid. */
void sock_init_data_uid(struct socket *sock, struct sock *sk, kuid_t uid);
/* Initialise core socket variables.
* Assumes struct socket *sock is embedded in a struct socket_alloc.
*/
void sock_init_data(struct socket *sock, struct sock *sk); void sock_init_data(struct socket *sock, struct sock *sk);
/* /*
......
...@@ -442,7 +442,7 @@ static inline bool is_tx_ready(struct tls_sw_context_tx *ctx) ...@@ -442,7 +442,7 @@ static inline bool is_tx_ready(struct tls_sw_context_tx *ctx)
{ {
struct tls_rec *rec; struct tls_rec *rec;
rec = list_first_entry(&ctx->tx_list, struct tls_rec, list); rec = list_first_entry_or_null(&ctx->tx_list, struct tls_rec, list);
if (!rec) if (!rec)
return false; return false;
......
...@@ -1376,19 +1376,6 @@ static int rb_check_bpage(struct ring_buffer_per_cpu *cpu_buffer, ...@@ -1376,19 +1376,6 @@ static int rb_check_bpage(struct ring_buffer_per_cpu *cpu_buffer,
return 0; return 0;
} }
/**
* rb_check_list - make sure a pointer to a list has the last bits zero
*/
static int rb_check_list(struct ring_buffer_per_cpu *cpu_buffer,
struct list_head *list)
{
if (RB_WARN_ON(cpu_buffer, rb_list_head(list->prev) != list->prev))
return 1;
if (RB_WARN_ON(cpu_buffer, rb_list_head(list->next) != list->next))
return 1;
return 0;
}
/** /**
* rb_check_pages - integrity check of buffer pages * rb_check_pages - integrity check of buffer pages
* @cpu_buffer: CPU buffer with pages to test * @cpu_buffer: CPU buffer with pages to test
...@@ -1398,36 +1385,27 @@ static int rb_check_list(struct ring_buffer_per_cpu *cpu_buffer, ...@@ -1398,36 +1385,27 @@ static int rb_check_list(struct ring_buffer_per_cpu *cpu_buffer,
*/ */
static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer) static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
{ {
struct list_head *head = cpu_buffer->pages; struct list_head *head = rb_list_head(cpu_buffer->pages);
struct buffer_page *bpage, *tmp; struct list_head *tmp;
/* Reset the head page if it exists */ if (RB_WARN_ON(cpu_buffer,
if (cpu_buffer->head_page) rb_list_head(rb_list_head(head->next)->prev) != head))
rb_set_head_page(cpu_buffer);
rb_head_page_deactivate(cpu_buffer);
if (RB_WARN_ON(cpu_buffer, head->next->prev != head))
return -1;
if (RB_WARN_ON(cpu_buffer, head->prev->next != head))
return -1; return -1;
if (rb_check_list(cpu_buffer, head)) if (RB_WARN_ON(cpu_buffer,
rb_list_head(rb_list_head(head->prev)->next) != head))
return -1; return -1;
list_for_each_entry_safe(bpage, tmp, head, list) { for (tmp = rb_list_head(head->next); tmp != head; tmp = rb_list_head(tmp->next)) {
if (RB_WARN_ON(cpu_buffer, if (RB_WARN_ON(cpu_buffer,
bpage->list.next->prev != &bpage->list)) rb_list_head(rb_list_head(tmp->next)->prev) != tmp))
return -1; return -1;
if (RB_WARN_ON(cpu_buffer, if (RB_WARN_ON(cpu_buffer,
bpage->list.prev->next != &bpage->list)) rb_list_head(rb_list_head(tmp->prev)->next) != tmp))
return -1;
if (rb_check_list(cpu_buffer, &bpage->list))
return -1; return -1;
} }
rb_head_page_activate(cpu_buffer);
return 0; return 0;
} }
......
...@@ -242,7 +242,7 @@ static int neigh_forced_gc(struct neigh_table *tbl) ...@@ -242,7 +242,7 @@ static int neigh_forced_gc(struct neigh_table *tbl)
(n->nud_state == NUD_NOARP) || (n->nud_state == NUD_NOARP) ||
(tbl->is_multicast && (tbl->is_multicast &&
tbl->is_multicast(n->primary_key)) || tbl->is_multicast(n->primary_key)) ||
time_after(tref, n->updated)) !time_in_range(n->updated, tref, jiffies))
remove = true; remove = true;
write_unlock(&n->lock); write_unlock(&n->lock);
...@@ -262,7 +262,17 @@ static int neigh_forced_gc(struct neigh_table *tbl) ...@@ -262,7 +262,17 @@ static int neigh_forced_gc(struct neigh_table *tbl)
static void neigh_add_timer(struct neighbour *n, unsigned long when) static void neigh_add_timer(struct neighbour *n, unsigned long when)
{ {
/* Use safe distance from the jiffies - LONG_MAX point while timer
* is running in DELAY/PROBE state but still show to user space
* large times in the past.
*/
unsigned long mint = jiffies - (LONG_MAX - 86400 * HZ);
neigh_hold(n); neigh_hold(n);
if (!time_in_range(n->confirmed, mint, jiffies))
n->confirmed = mint;
if (time_before(n->used, n->confirmed))
n->used = n->confirmed;
if (unlikely(mod_timer(&n->timer, when))) { if (unlikely(mod_timer(&n->timer, when))) {
printk("NEIGH: BUG, double timer add, state is %x\n", printk("NEIGH: BUG, double timer add, state is %x\n",
n->nud_state); n->nud_state);
...@@ -948,12 +958,14 @@ static void neigh_periodic_work(struct work_struct *work) ...@@ -948,12 +958,14 @@ static void neigh_periodic_work(struct work_struct *work)
goto next_elt; goto next_elt;
} }
if (time_before(n->used, n->confirmed)) if (time_before(n->used, n->confirmed) &&
time_is_before_eq_jiffies(n->confirmed))
n->used = n->confirmed; n->used = n->confirmed;
if (refcount_read(&n->refcnt) == 1 && if (refcount_read(&n->refcnt) == 1 &&
(state == NUD_FAILED || (state == NUD_FAILED ||
time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { !time_in_range_open(jiffies, n->used,
n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
*np = n->next; *np = n->next;
neigh_mark_dead(n); neigh_mark_dead(n);
write_unlock(&n->lock); write_unlock(&n->lock);
......
...@@ -2967,7 +2967,7 @@ void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer) ...@@ -2967,7 +2967,7 @@ void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer)
} }
EXPORT_SYMBOL(sk_stop_timer_sync); EXPORT_SYMBOL(sk_stop_timer_sync);
void sock_init_data(struct socket *sock, struct sock *sk) void sock_init_data_uid(struct socket *sock, struct sock *sk, kuid_t uid)
{ {
sk_init_common(sk); sk_init_common(sk);
sk->sk_send_head = NULL; sk->sk_send_head = NULL;
...@@ -2986,13 +2986,12 @@ void sock_init_data(struct socket *sock, struct sock *sk) ...@@ -2986,13 +2986,12 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->sk_type = sock->type; sk->sk_type = sock->type;
RCU_INIT_POINTER(sk->sk_wq, &sock->wq); RCU_INIT_POINTER(sk->sk_wq, &sock->wq);
sock->sk = sk; sock->sk = sk;
sk->sk_uid = SOCK_INODE(sock)->i_uid;
sk->sk_gid = SOCK_INODE(sock)->i_gid; sk->sk_gid = SOCK_INODE(sock)->i_gid;
} else { } else {
RCU_INIT_POINTER(sk->sk_wq, NULL); RCU_INIT_POINTER(sk->sk_wq, NULL);
sk->sk_uid = make_kuid(sock_net(sk)->user_ns, 0);
sk->sk_gid = make_kgid(sock_net(sk)->user_ns, 0); sk->sk_gid = make_kgid(sock_net(sk)->user_ns, 0);
} }
sk->sk_uid = uid;
rwlock_init(&sk->sk_callback_lock); rwlock_init(&sk->sk_callback_lock);
if (sk->sk_kern_sock) if (sk->sk_kern_sock)
...@@ -3050,6 +3049,16 @@ void sock_init_data(struct socket *sock, struct sock *sk) ...@@ -3050,6 +3049,16 @@ void sock_init_data(struct socket *sock, struct sock *sk)
refcount_set(&sk->sk_refcnt, 1); refcount_set(&sk->sk_refcnt, 1);
atomic_set(&sk->sk_drops, 0); atomic_set(&sk->sk_drops, 0);
} }
EXPORT_SYMBOL(sock_init_data_uid);
void sock_init_data(struct socket *sock, struct sock *sk)
{
kuid_t uid = sock ?
SOCK_INODE(sock)->i_uid :
make_kuid(sock_net(sk)->user_ns, 0);
sock_init_data_uid(sock, sk, uid);
}
EXPORT_SYMBOL(sock_init_data); EXPORT_SYMBOL(sock_init_data);
void lock_sock_nested(struct sock *sk, int subclass) void lock_sock_nested(struct sock *sk, int subclass)
......
...@@ -814,8 +814,7 @@ static void inet_clone_ulp(const struct request_sock *req, struct sock *newsk, ...@@ -814,8 +814,7 @@ static void inet_clone_ulp(const struct request_sock *req, struct sock *newsk,
if (!icsk->icsk_ulp_ops) if (!icsk->icsk_ulp_ops)
return; return;
if (icsk->icsk_ulp_ops->clone) icsk->icsk_ulp_ops->clone(req, newsk, priority);
icsk->icsk_ulp_ops->clone(req, newsk, priority);
} }
/** /**
...@@ -912,11 +911,25 @@ void inet_csk_prepare_forced_close(struct sock *sk) ...@@ -912,11 +911,25 @@ void inet_csk_prepare_forced_close(struct sock *sk)
} }
EXPORT_SYMBOL(inet_csk_prepare_forced_close); EXPORT_SYMBOL(inet_csk_prepare_forced_close);
static int inet_ulp_can_listen(const struct sock *sk)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
if (icsk->icsk_ulp_ops && !icsk->icsk_ulp_ops->clone)
return -EINVAL;
return 0;
}
int inet_csk_listen_start(struct sock *sk, int backlog) int inet_csk_listen_start(struct sock *sk, int backlog)
{ {
struct inet_connection_sock *icsk = inet_csk(sk); struct inet_connection_sock *icsk = inet_csk(sk);
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
int err = -EADDRINUSE; int err;
err = inet_ulp_can_listen(sk);
if (unlikely(err))
return err;
reqsk_queue_alloc(&icsk->icsk_accept_queue); reqsk_queue_alloc(&icsk->icsk_accept_queue);
...@@ -928,6 +941,7 @@ int inet_csk_listen_start(struct sock *sk, int backlog) ...@@ -928,6 +941,7 @@ int inet_csk_listen_start(struct sock *sk, int backlog)
* It is OK, because this socket enters to hash table only * It is OK, because this socket enters to hash table only
* after validation is complete. * after validation is complete.
*/ */
err = -EADDRINUSE;
inet_sk_state_store(sk, TCP_LISTEN); inet_sk_state_store(sk, TCP_LISTEN);
if (!sk->sk_prot->get_port(sk, inet->inet_num)) { if (!sk->sk_prot->get_port(sk, inet->inet_num)) {
inet->inet_sport = htons(inet->inet_num); inet->inet_sport = htons(inet->inet_num);
......
...@@ -136,6 +136,10 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops) ...@@ -136,6 +136,10 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
if (icsk->icsk_ulp_ops) if (icsk->icsk_ulp_ops)
goto out_err; goto out_err;
err = -ENOTCONN;
if (!ulp_ops->clone && sk->sk_state == TCP_LISTEN)
goto out_err;
err = ulp_ops->init(sk); err = ulp_ops->init(sk);
if (err) if (err)
goto out_err; goto out_err;
......
...@@ -104,9 +104,9 @@ static void rds_rm_zerocopy_callback(struct rds_sock *rs, ...@@ -104,9 +104,9 @@ static void rds_rm_zerocopy_callback(struct rds_sock *rs,
spin_lock_irqsave(&q->lock, flags); spin_lock_irqsave(&q->lock, flags);
head = &q->zcookie_head; head = &q->zcookie_head;
if (!list_empty(head)) { if (!list_empty(head)) {
info = list_entry(head, struct rds_msg_zcopy_info, info = list_first_entry(head, struct rds_msg_zcopy_info,
rs_zcookie_next); rs_zcookie_next);
if (info && rds_zcookie_add(info, cookie)) { if (rds_zcookie_add(info, cookie)) {
spin_unlock_irqrestore(&q->lock, flags); spin_unlock_irqrestore(&q->lock, flags);
kfree(rds_info_from_znotifier(znotif)); kfree(rds_info_from_znotifier(znotif));
/* caller invokes rds_wake_sk_sleep() */ /* caller invokes rds_wake_sk_sleep() */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册