diff options
author | Luiz Souza <luiz@netgate.com> | 2018-05-08 15:29:57 -0300 |
---|---|---|
committer | Luiz Souza <luiz@netgate.com> | 2018-05-08 15:29:57 -0300 |
commit | 61033f55dc6b6b9c295e0ade753c1d0b142ddd1b (patch) | |
tree | dca9d1eea2391625aced6348fd39db2bd5c8cf3a /sys | |
parent | ed209f46dbcc4a79d277e0d2e93dc51a1f331be5 (diff) | |
parent | 2128561f0f5745f9e9330fbd5910e68e71159fcc (diff) | |
download | FreeBSD-src-61033f55dc6b6b9c295e0ade753c1d0b142ddd1b.zip FreeBSD-src-61033f55dc6b6b9c295e0ade753c1d0b142ddd1b.tar.gz |
Merge remote-tracking branch 'origin/releng/11.1' into RELENG_2_4
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/amd64/exception.S | 116 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 13 | ||||
-rw-r--r-- | sys/amd64/amd64/mp_machdep.c | 11 | ||||
-rw-r--r-- | sys/amd64/amd64/pmap.c | 3 | ||||
-rw-r--r-- | sys/amd64/amd64/trap.c | 57 | ||||
-rw-r--r-- | sys/compat/linux/linux_ioctl.c | 2 | ||||
-rw-r--r-- | sys/compat/linux/linux_ipc.c | 10 | ||||
-rw-r--r-- | sys/conf/newvers.sh | 2 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_btcoex.c | 3 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_ioctl.c | 2 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_lna_div.c | 3 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_spectral.c | 3 | ||||
-rw-r--r-- | sys/i386/i386/trap.c | 30 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 4 |
14 files changed, 247 insertions, 12 deletions
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index b89c2eb..e3afe22 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -116,7 +116,6 @@ X\l: subq $TF_RIP,%rsp jmp alltraps_noen .endm - TRAP_NOEN dbg, T_TRCTRAP TRAP_NOEN bpt, T_BPTFLT #ifdef KDTRACE_HOOKS TRAP_NOEN dtrace_ret, T_DTRACE_RET @@ -525,6 +524,121 @@ IDTVEC(fast_syscall32) sysret /* + * DB# handler is very similar to NM#, because 'mov/pop %ss' delay + * generation of exception until the next instruction is executed, + * which might be a kernel entry. So we must execute the handler + * on IST stack and be ready for non-kernel GSBASE. + */ +IDTVEC(dbg) + subq $TF_RIP,%rsp + movl $(T_TRCTRAP),TF_TRAPNO(%rsp) + movq $0,TF_ADDR(%rsp) + movq $0,TF_ERR(%rsp) + movq %rdi,TF_RDI(%rsp) + movq %rsi,TF_RSI(%rsp) + movq %rdx,TF_RDX(%rsp) + movq %rcx,TF_RCX(%rsp) + movq %r8,TF_R8(%rsp) + movq %r9,TF_R9(%rsp) + movq %rax,TF_RAX(%rsp) + movq %rbx,TF_RBX(%rsp) + movq %rbp,TF_RBP(%rsp) + movq %r10,TF_R10(%rsp) + movq %r11,TF_R11(%rsp) + movq %r12,TF_R12(%rsp) + movq %r13,TF_R13(%rsp) + movq %r14,TF_R14(%rsp) + movq %r15,TF_R15(%rsp) + SAVE_SEGS + movl $TF_HASSEGS,TF_FLAGS(%rsp) + cld + testb $SEL_RPL_MASK,TF_CS(%rsp) + jnz dbg_fromuserspace + /* + * We've interrupted the kernel. Preserve GS.base in %r12, + * %cr3 in %r13, and possibly lower half of MSR_IA32_SPEC_CTL in %r14d. + */ + movl $MSR_GSBASE,%ecx + rdmsr + movq %rax,%r12 + shlq $32,%rdx + orq %rdx,%r12 + /* Retrieve and load the canonical value for GS.base. */ + movq TF_SIZE(%rsp),%rdx + movl %edx,%eax + shrq $32,%rdx + wrmsr + movq %cr3,%r13 + movq PCPU(KCR3),%rax + cmpq $~0,%rax + je 1f + movq %rax,%cr3 +1: testl $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip) + je 2f + movl $MSR_IA32_SPEC_CTRL,%ecx + rdmsr + movl %eax,%r14d + call handle_ibrs_entry +2: FAKE_MCOUNT(TF_RIP(%rsp)) + movq %rsp,%rdi + call trap + MEXITCOUNT + testl $CPUID_STDEXT3_IBPB,cpu_stdext_feature3(%rip) + je 3f + movl %r14d,%eax + xorl %edx,%edx + movl $MSR_IA32_SPEC_CTRL,%ecx + wrmsr + /* + * Put back the preserved MSR_GSBASE value. + */ +3: movl $MSR_GSBASE,%ecx + movq %r12,%rdx + movl %edx,%eax + shrq $32,%rdx + wrmsr + movq %r13,%cr3 + RESTORE_REGS + addq $TF_RIP,%rsp + jmp doreti_iret +dbg_fromuserspace: + /* + * Switch to kernel GSBASE and kernel page table, and copy frame + * from the IST stack to the normal kernel stack, since trap() + * re-enables interrupts, and since we might trap on DB# while + * in trap(). + */ + swapgs + movq PCPU(KCR3),%rax + cmpq $~0,%rax + je 1f + movq %rax,%cr3 +1: movq PCPU(RSP0),%rax + movl $TF_SIZE,%ecx + subq %rcx,%rax + movq %rax,%rdi + movq %rsp,%rsi + rep;movsb + movq %rax,%rsp + call handle_ibrs_entry + movq PCPU(CURPCB),%rdi + orl $PCB_FULL_IRET,PCB_FLAGS(%rdi) + testb $CPUID_STDEXT_FSGSBASE,cpu_stdext_feature(%rip) + jz 3f + cmpw $KUF32SEL,TF_FS(%rsp) + jne 2f + rdfsbase %rax + movq %rax,PCB_FSBASE(%rdi) +2: cmpw $KUG32SEL,TF_GS(%rsp) + jne 3f + movl $MSR_KGSBASE,%ecx + rdmsr + shlq $32,%rdx + orq %rdx,%rax + movq %rax,PCB_GSBASE(%rdi) +3: jmp calltrap + +/* * NMI handling is special. * * First, NMIs do not respect the state of the processor's RFLAGS.IF diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 51b8433..ab48566 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -675,6 +675,7 @@ struct gate_descriptor *idt = &idt0[0]; /* interrupt descriptor table */ static char dblfault_stack[PAGE_SIZE] __aligned(16); static char mce0_stack[PAGE_SIZE] __aligned(16); static char nmi0_stack[PAGE_SIZE] __aligned(16); +static char dbg0_stack[PAGE_SIZE] __aligned(16); CTASSERT(sizeof(struct nmi_pcpu) == 16); struct amd64tss common_tss[MAXCPU]; @@ -827,7 +828,7 @@ extern inthand_t IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), IDTVEC(xmm), IDTVEC(dblfault), - IDTVEC(div_pti), IDTVEC(dbg_pti), IDTVEC(bpt_pti), + IDTVEC(div_pti), IDTVEC(bpt_pti), IDTVEC(ofl_pti), IDTVEC(bnd_pti), IDTVEC(ill_pti), IDTVEC(dna_pti), IDTVEC(fpusegm_pti), IDTVEC(tss_pti), IDTVEC(missing_pti), IDTVEC(stk_pti), IDTVEC(prot_pti), IDTVEC(page_pti), @@ -1638,8 +1639,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) SEL_KPL, 0); setidt(IDT_DE, pti ? &IDTVEC(div_pti) : &IDTVEC(div), SDT_SYSIGT, SEL_KPL, 0); - setidt(IDT_DB, pti ? &IDTVEC(dbg_pti) : &IDTVEC(dbg), SDT_SYSIGT, - SEL_KPL, 0); + setidt(IDT_DB, &IDTVEC(dbg), SDT_SYSIGT, SEL_KPL, 4); setidt(IDT_NMI, &IDTVEC(nmi), SDT_SYSIGT, SEL_KPL, 2); setidt(IDT_BP, pti ? &IDTVEC(bpt_pti) : &IDTVEC(bpt), SDT_SYSIGT, SEL_UPL, 0); @@ -1721,6 +1721,13 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) np = ((struct nmi_pcpu *) &mce0_stack[sizeof(mce0_stack)]) - 1; np->np_pcpu = (register_t) pc; common_tss[0].tss_ist3 = (long) np; + + /* + * DB# stack, runs on ist4. + */ + np = ((struct nmi_pcpu *) &dbg0_stack[sizeof(dbg0_stack)]) - 1; + np->np_pcpu = (register_t) pc; + common_tss[0].tss_ist4 = (long) np; /* Set the IO permission bitmap (empty due to tss seg limit) */ common_tss[0].tss_iobase = sizeof(struct amd64tss) + IOPERM_BITMAP_SIZE; diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 450d512..34a05e9 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -87,6 +87,7 @@ extern struct pcpu __pcpu[]; char *doublefault_stack; char *mce_stack; char *nmi_stack; +char *dbg_stack; /* * Local data and functions. @@ -225,6 +226,10 @@ init_secondary(void) np = ((struct nmi_pcpu *) &mce_stack[PAGE_SIZE]) - 1; common_tss[cpu].tss_ist3 = (long) np; + /* The DB# stack runs on IST4. */ + np = ((struct nmi_pcpu *) &dbg_stack[PAGE_SIZE]) - 1; + common_tss[cpu].tss_ist4 = (long) np; + /* Prepare private GDT */ gdt_segs[GPROC0_SEL].ssd_base = (long) &common_tss[cpu]; for (x = 0; x < NGDT; x++) { @@ -270,6 +275,10 @@ init_secondary(void) np = ((struct nmi_pcpu *) &mce_stack[PAGE_SIZE]) - 1; np->np_pcpu = (register_t) pc; + /* Save the per-cpu pointer for use by the DB# handler. */ + np = ((struct nmi_pcpu *) &dbg_stack[PAGE_SIZE]) - 1; + np->np_pcpu = (register_t) pc; + wrmsr(MSR_FSBASE, 0); /* User value */ wrmsr(MSR_GSBASE, (u_int64_t)pc); wrmsr(MSR_KGSBASE, (u_int64_t)pc); /* XXX User value while we're in the kernel */ @@ -368,6 +377,8 @@ native_start_all_aps(void) M_WAITOK | M_ZERO); nmi_stack = (char *)kmem_malloc(kernel_arena, PAGE_SIZE, M_WAITOK | M_ZERO); + dbg_stack = (char *)kmem_malloc(kernel_arena, PAGE_SIZE, + M_WAITOK | M_ZERO); dpcpu = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE, M_WAITOK | M_ZERO); diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 64abe9b..53de162 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -7564,6 +7564,9 @@ pmap_pti_init(void) /* MC# stack IST 3 */ va = common_tss[i].tss_ist3 + sizeof(struct nmi_pcpu); pmap_pti_add_kva_locked(va - PAGE_SIZE, va, false); + /* DB# stack IST 4 */ + va = common_tss[i].tss_ist4 + sizeof(struct nmi_pcpu); + pmap_pti_add_kva_locked(va - PAGE_SIZE, va, false); } pmap_pti_add_kva_locked((vm_offset_t)kernphys + KERNBASE, (vm_offset_t)etext, true); diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index a553fc5..4562902 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); */ #include "opt_clock.h" +#include "opt_compat.h" #include "opt_cpu.h" #include "opt_hwpmc_hooks.h" #include "opt_isa.h" @@ -99,8 +100,14 @@ PMC_SOFT_DEFINE( , , page_fault, write); #include <sys/dtrace_bsd.h> #endif -void __noinline trap(struct trapframe *frame); -void trap_check(struct trapframe *frame); +extern inthand_t IDTVEC(bpt), IDTVEC(bpt_pti), IDTVEC(dbg), + IDTVEC(fast_syscall), IDTVEC(fast_syscall_pti), IDTVEC(fast_syscall32), + IDTVEC(int0x80_syscall_pti), IDTVEC(int0x80_syscall); + + +extern void __noinline trap(struct trapframe *frame); +extern void trap_check(struct trapframe *frame); +extern void syscall(struct trapframe *frame); void dblfault_handler(struct trapframe *frame); static int trap_pfault(struct trapframe *, int); @@ -535,6 +542,52 @@ trap(struct trapframe *frame) load_dr6(rdr6() & ~0xf); return; } + + /* + * Malicious user code can configure a debug + * register watchpoint to trap on data access + * to the top of stack and then execute 'pop + * %ss; int 3'. Due to exception deferral for + * 'pop %ss', the CPU will not interrupt 'int + * 3' to raise the DB# exception for the debug + * register but will postpone the DB# until + * execution of the first instruction of the + * BP# handler (in kernel mode). Normally the + * previous check would ignore DB# exceptions + * for watchpoints on user addresses raised in + * kernel mode. However, some CPU errata + * include cases where DB# exceptions do not + * properly set bits in %dr6, e.g. Haswell + * HSD23 and Skylake-X SKZ24. + * + * A deferred DB# can also be raised on the + * first instructions of system call entry + * points or single-step traps via similar use + * of 'pop %ss' or 'mov xxx, %ss'. + */ + if (pti) { + if (frame->tf_rip == + (uintptr_t)IDTVEC(fast_syscall_pti) || +#ifdef COMPAT_FREEBSD32 + frame->tf_rip == + (uintptr_t)IDTVEC(int0x80_syscall_pti) || +#endif + frame->tf_rip == (uintptr_t)IDTVEC(bpt_pti)) + return; + } else { + if (frame->tf_rip == + (uintptr_t)IDTVEC(fast_syscall) || +#ifdef COMPAT_FREEBSD32 + frame->tf_rip == + (uintptr_t)IDTVEC(int0x80_syscall) || +#endif + frame->tf_rip == (uintptr_t)IDTVEC(bpt)) + return; + } + if (frame->tf_rip == (uintptr_t)IDTVEC(dbg) || + /* Needed for AMD. */ + frame->tf_rip == (uintptr_t)IDTVEC(fast_syscall32)) + return; /* * FALLTHROUGH (TRCTRAP kernel mode, kernel address) */ diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index b77db6c..5c30c19 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -253,6 +253,7 @@ linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args) } else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) { struct linux_hd_big_geometry hdbg; + memset(&hdbg, 0, sizeof(hdbg)); hdbg.cylinders = fwcylinders; hdbg.heads = fwheads; hdbg.sectors = fwsectors; @@ -2477,6 +2478,7 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) printf("%s(): ioctl %d on %.*s\n", __func__, args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname); #endif + memset(ifname, 0, sizeof(ifname)); ifp = ifname_linux_to_bsd(td, lifname, ifname); if (ifp == NULL) return (EINVAL); diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c index 9fa1fed..cd01c41 100644 --- a/sys/compat/linux/linux_ipc.c +++ b/sys/compat/linux/linux_ipc.c @@ -548,6 +548,9 @@ linux_semctl(struct thread *td, struct linux_semctl_args *args) register_t rval; int cmd, error; + memset(&linux_seminfo, 0, sizeof(linux_seminfo)); + memset(&linux_semid64, 0, sizeof(linux_semid64)); + switch (args->cmd & ~LINUX_IPC_64) { case LINUX_IPC_RMID: cmd = IPC_RMID; @@ -702,12 +705,15 @@ linux_msgctl(struct thread *td, struct linux_msgctl_args *args) struct l_msqid64_ds linux_msqid64; struct msqid_ds bsd_msqid; + memset(&linux_msqid64, 0, sizeof(linux_msqid64)); + bsd_cmd = args->cmd & ~LINUX_IPC_64; switch (bsd_cmd) { case LINUX_IPC_INFO: case LINUX_MSG_INFO: { struct l_msginfo linux_msginfo; + memset(&linux_msginfo, 0, sizeof(linux_msginfo)); /* * XXX MSG_INFO uses the same data structure but returns different * dynamic counters in msgpool, msgmap, and msgtql fields. @@ -833,6 +839,10 @@ linux_shmctl(struct thread *td, struct linux_shmctl_args *args) struct shmid_ds bsd_shmid; int error; + memset(&linux_shm_info, 0, sizeof(linux_shm_info)); + memset(&linux_shmid64, 0, sizeof(linux_shmid64)); + memset(&linux_shminfo64, 0, sizeof(linux_shminfo64)); + switch (args->cmd & ~LINUX_IPC_64) { case LINUX_IPC_INFO: { diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index f296585..e2d1727 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -44,7 +44,7 @@ TYPE="FreeBSD" REVISION="11.1" -BRANCH="RELEASE-p9" +BRANCH="RELEASE-p10" if [ -n "${BRANCH_OVERRIDE}" ]; then BRANCH=${BRANCH_OVERRIDE} fi diff --git a/sys/dev/ath/if_ath_btcoex.c b/sys/dev/ath/if_ath_btcoex.c index f071fc4..002483a 100644 --- a/sys/dev/ath/if_ath_btcoex.c +++ b/sys/dev/ath/if_ath_btcoex.c @@ -457,7 +457,7 @@ ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad) * pointer for us to use below in reclaiming the buffer; * may want to be more defensive. */ - outdata = malloc(outsize, M_TEMP, M_NOWAIT); + outdata = malloc(outsize, M_TEMP, M_NOWAIT | M_ZERO); if (outdata == NULL) { error = ENOMEM; goto bad; @@ -466,6 +466,7 @@ ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad) switch (id) { default: error = EINVAL; + goto bad; } if (outsize < ad->ad_out_size) ad->ad_out_size = outsize; diff --git a/sys/dev/ath/if_ath_ioctl.c b/sys/dev/ath/if_ath_ioctl.c index 1128c18..73c1ca2 100644 --- a/sys/dev/ath/if_ath_ioctl.c +++ b/sys/dev/ath/if_ath_ioctl.c @@ -197,7 +197,7 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad) * pointer for us to use below in reclaiming the buffer; * may want to be more defensive. */ - outdata = malloc(outsize, M_TEMP, M_NOWAIT); + outdata = malloc(outsize, M_TEMP, M_NOWAIT | M_ZERO); if (outdata == NULL) { error = ENOMEM; goto bad; diff --git a/sys/dev/ath/if_ath_lna_div.c b/sys/dev/ath/if_ath_lna_div.c index 5c102fb..ec85924 100644 --- a/sys/dev/ath/if_ath_lna_div.c +++ b/sys/dev/ath/if_ath_lna_div.c @@ -187,7 +187,7 @@ ath_lna_div_ioctl(struct ath_softc *sc, struct ath_diag *ad) * pointer for us to use below in reclaiming the buffer; * may want to be more defensive. */ - outdata = malloc(outsize, M_TEMP, M_NOWAIT); + outdata = malloc(outsize, M_TEMP, M_NOWAIT | M_ZERO); if (outdata == NULL) { error = ENOMEM; goto bad; @@ -196,6 +196,7 @@ ath_lna_div_ioctl(struct ath_softc *sc, struct ath_diag *ad) switch (id) { default: error = EINVAL; + goto bad; } if (outsize < ad->ad_out_size) ad->ad_out_size = outsize; diff --git a/sys/dev/ath/if_ath_spectral.c b/sys/dev/ath/if_ath_spectral.c index e4afdae..d8f9e8a 100644 --- a/sys/dev/ath/if_ath_spectral.c +++ b/sys/dev/ath/if_ath_spectral.c @@ -212,7 +212,7 @@ ath_ioctl_spectral(struct ath_softc *sc, struct ath_diag *ad) * pointer for us to use below in reclaiming the buffer; * may want to be more defensive. */ - outdata = malloc(outsize, M_TEMP, M_NOWAIT); + outdata = malloc(outsize, M_TEMP, M_NOWAIT | M_ZERO); if (outdata == NULL) { error = ENOMEM; goto bad; @@ -275,6 +275,7 @@ ath_ioctl_spectral(struct ath_softc *sc, struct ath_diag *ad) break; default: error = EINVAL; + goto bad; } if (outsize < ad->ad_out_size) ad->ad_out_size = outsize; diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 000ff17..7fa94f4 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -116,6 +116,8 @@ void dblfault_handler(void); extern inthand_t IDTVEC(lcall_syscall); +extern inthand_t IDTVEC(bpt), IDTVEC(dbg), IDTVEC(int0x80_syscall); + #define MAX_TRAP_MSG 32 static char *trap_msg[] = { "", /* 0 unused */ @@ -668,6 +670,34 @@ kernel_trctrap: load_dr6(rdr6() & ~0xf); goto out; } + + /* + * Malicious user code can configure a debug + * register watchpoint to trap on data access + * to the top of stack and then execute 'pop + * %ss; int 3'. Due to exception deferral for + * 'pop %ss', the CPU will not interrupt 'int + * 3' to raise the DB# exception for the debug + * register but will postpone the DB# until + * execution of the first instruction of the + * BP# handler (in kernel mode). Normally the + * previous check would ignore DB# exceptions + * for watchpoints on user addresses raised in + * kernel mode. However, some CPU errata + * include cases where DB# exceptions do not + * properly set bits in %dr6, e.g. Haswell + * HSD23 and Skylake-X SKZ24. + * + * A deferred DB# can also be raised on the + * first instructions of system call entry + * points or single-step traps via similar use + * of 'pop %ss' or 'mov xxx, %ss'. + */ + if (frame->tf_eip == + (uintptr_t)IDTVEC(int0x80_syscall) || + frame->tf_eip == (uintptr_t)IDTVEC(bpt) || + frame->tf_eip == (uintptr_t)IDTVEC(dbg)) + return; /* * FALLTHROUGH (TRCTRAP kernel mode, kernel address) */ diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 6a7bf00..64f8562 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1495,7 +1495,9 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt) return (error); } else if ((sopt->sopt_dir == SOPT_GET) && (sopt->sopt_name == TCP_FUNCTION_BLK)) { - strcpy(fsn.function_set_name, tp->t_fb->tfb_tcp_block_name); + strncpy(fsn.function_set_name, tp->t_fb->tfb_tcp_block_name, + TCP_FUNCTION_NAME_LEN_MAX); + fsn.function_set_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0'; fsn.pcbcnt = tp->t_fb->tfb_refcnt; INP_WUNLOCK(inp); error = sooptcopyout(sopt, &fsn, sizeof fsn); |