Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1240063 > unrolled thread
| Started by | Andy Lutomirski <luto@kernel.org> |
|---|---|
| First post | 2015-10-06 02:50 +0200 |
| Last post | 2015-10-14 18:40 +0200 |
| Articles | 5 — 4 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH v2 24/36] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls Andy Lutomirski <luto@kernel.org> - 2015-10-06 02:50 +0200
[tip:x86/asm] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls tip-bot for Andy Lutomirski <tipbot@zytor.com> - 2015-10-09 15:20 +0200
Re: [PATCH v2 24/36] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls Borislav Petkov <bp@alien8.de> - 2015-10-12 18:20 +0200
Re: [PATCH v2 24/36] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls Andy Lutomirski <luto@amacapital.net> - 2015-10-14 18:30 +0200
Re: [PATCH v2 24/36] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls Borislav Petkov <bp@alien8.de> - 2015-10-14 18:40 +0200
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-10-06 02:50 +0200 |
| Subject | [PATCH v2 24/36] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls |
| Message-ID | <qgoC7-715-37@gated-at.bofh.it> |
If CS, SS and IP are as expected and FLAGS is compatible with SYSRETL,
then return from fast compat syscalls (both SYSCALL and SYSENTER) using
SYSRETL.
Unlike native 64-bit opportunistic SYSRET, this is not invisible to
user code: RCX and R8-R15 end up in a different state than shown
saved in pt_regs. To compensate, we only do this when returning to
the vDSO fast syscall return path. This won't interfere with
syscall restart, as we won't use SYSRETL when returning to the INT80
restart instruction.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
arch/x86/entry/common.c | 23 +++++++++++++++++++---
arch/x86/entry/entry_64_compat.S | 42 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 1b2606edc621..88dc5ba14d47 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -363,7 +363,8 @@ __visible void do_int80_syscall_32(struct pt_regs *regs)
syscall_return_slowpath(regs);
}
-__visible void do_fast_syscall_32(struct pt_regs *regs)
+/* Returns 0 to return using IRET or 1 to return using SYSRETL. */
+__visible long do_fast_syscall_32(struct pt_regs *regs)
{
/*
* Called using the internal vDSO SYSENTER/SYSCALL32 calling
@@ -395,12 +396,28 @@ __visible void do_fast_syscall_32(struct pt_regs *regs)
enter_from_user_mode();
#endif
prepare_exit_to_usermode(regs);
- return;
+ return 0; /* Keep it simple: use IRET. */
}
local_irq_disable();
/* Now this is just like a normal syscall. */
do_int80_syscall_32(regs);
- return;
+
+#ifdef CONFIG_X86_64
+ /*
+ * Opportunistic SYSRETL: if possible, try to return using SYSRETL.
+ * SYSRETL is available on all 64-bit CPUs, so we don't need to
+ * bother with SYSEXIT.
+ *
+ * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
+ * because the ECX fixup above will ensure that this is essentially
+ * never the case.
+ */
+ return regs->cs == __USER32_CS && regs->ss == __USER_DS &&
+ regs->ip == landing_pad &&
+ (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF)) == 0;
+#else
+ return 0;
+#endif
}
#endif
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 8f109de51d03..cf9641cd4796 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -115,7 +115,9 @@ sysenter_flags_fixed:
movq %rsp, %rdi
call do_fast_syscall_32
- jmp .Lsyscall_32_done
+ testl %eax, %eax
+ jz .Lsyscall_32_done
+ jmp sysret32_from_system_call
sysenter_fix_flags:
pushq $X86_EFLAGS_FIXED
@@ -192,7 +194,43 @@ ENTRY(entry_SYSCALL_compat)
movq %rsp, %rdi
call do_fast_syscall_32
- jmp .Lsyscall_32_done
+ testl %eax, %eax
+ jz .Lsyscall_32_done
+
+ /* Opportunistic SYSRET */
+sysret32_from_system_call:
+ TRACE_IRQS_ON /* User mode traces as IRQs on. */
+ movq RBX(%rsp), %rbx /* pt_regs->rbx */
+ movq RBP(%rsp), %rbp /* pt_regs->rbp */
+ movq EFLAGS(%rsp), %r11 /* pt_regs->flags (in r11) */
+ movq RIP(%rsp), %rcx /* pt_regs->ip (in rcx) */
+ addq $RAX, %rsp /* Skip r8-r15 */
+ popq %rax /* pt_regs->rax */
+ popq %rdx /* Skip pt_regs->cx */
+ popq %rdx /* pt_regs->dx */
+ popq %rsi /* pt_regs->si */
+ popq %rdi /* pt_regs->di */
+
+ /*
+ * USERGS_SYSRET32 does:
+ * GSBASE = user's GS base
+ * EIP = ECX
+ * RFLAGS = R11
+ * CS = __USER32_CS
+ * SS = __USER_DS
+ *
+ * ECX will not match pt_regs->cx, but we're returning to a vDSO
+ * trampoline that will fix up RCX, so this is okay.
+ *
+ * R12-R15 are callee-saved, so they contain whatever was in them
+ * when the system call started, which is already known to user
+ * code. We zero R8-R10 to avoid info leaks.
+ */
+ xorq %r8, %r8
+ xorq %r9, %r9
+ xorq %r10, %r10
+ movq RSP-ORIG_RAX(%rsp), %rsp
+ USERGS_SYSRET32
END(entry_SYSCALL_compat)
/*
--
2.4.3
--
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/
[toc] | [next] | [standalone]
| From | tip-bot for Andy Lutomirski <tipbot@zytor.com> |
|---|---|
| Date | 2015-10-09 15:20 +0200 |
| Subject | [tip:x86/asm] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls |
| Message-ID | <qhFKy-3bI-29@gated-at.bofh.it> |
| In reply to | #1240063 |
Commit-ID: 7841b408717d4c3b1b334c8f1fef7f18c98cd2bd
Gitweb: http://git.kernel.org/tip/7841b408717d4c3b1b334c8f1fef7f18c98cd2bd
Author: Andy Lutomirski <luto@kernel.org>
AuthorDate: Mon, 5 Oct 2015 17:48:12 -0700
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Fri, 9 Oct 2015 09:41:10 +0200
x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls
If CS, SS and IP are as expected and FLAGS is compatible with
SYSRETL, then return from fast compat syscalls (both SYSCALL and
SYSENTER) using SYSRETL.
Unlike native 64-bit opportunistic SYSRET, this is not invisible
to user code: RCX and R8-R15 end up in a different state than
shown saved in pt_regs. To compensate, we only do this when
returning to the vDSO fast syscall return path. This won't
interfere with syscall restart, as we won't use SYSRETL when
returning to the INT80 restart instruction.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Link: http://lkml.kernel.org/r/aa15e49db33773eb10b73d73466b6d5466d7856a.1444091585.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/entry/common.c | 23 +++++++++++++++++++---
arch/x86/entry/entry_64_compat.S | 42 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 1b2606e..88dc5ba 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -363,7 +363,8 @@ __visible void do_int80_syscall_32(struct pt_regs *regs)
syscall_return_slowpath(regs);
}
-__visible void do_fast_syscall_32(struct pt_regs *regs)
+/* Returns 0 to return using IRET or 1 to return using SYSRETL. */
+__visible long do_fast_syscall_32(struct pt_regs *regs)
{
/*
* Called using the internal vDSO SYSENTER/SYSCALL32 calling
@@ -395,12 +396,28 @@ __visible void do_fast_syscall_32(struct pt_regs *regs)
enter_from_user_mode();
#endif
prepare_exit_to_usermode(regs);
- return;
+ return 0; /* Keep it simple: use IRET. */
}
local_irq_disable();
/* Now this is just like a normal syscall. */
do_int80_syscall_32(regs);
- return;
+
+#ifdef CONFIG_X86_64
+ /*
+ * Opportunistic SYSRETL: if possible, try to return using SYSRETL.
+ * SYSRETL is available on all 64-bit CPUs, so we don't need to
+ * bother with SYSEXIT.
+ *
+ * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
+ * because the ECX fixup above will ensure that this is essentially
+ * never the case.
+ */
+ return regs->cs == __USER32_CS && regs->ss == __USER_DS &&
+ regs->ip == landing_pad &&
+ (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF)) == 0;
+#else
+ return 0;
+#endif
}
#endif
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 8f109de5..cf9641c 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -115,7 +115,9 @@ sysenter_flags_fixed:
movq %rsp, %rdi
call do_fast_syscall_32
- jmp .Lsyscall_32_done
+ testl %eax, %eax
+ jz .Lsyscall_32_done
+ jmp sysret32_from_system_call
sysenter_fix_flags:
pushq $X86_EFLAGS_FIXED
@@ -192,7 +194,43 @@ ENTRY(entry_SYSCALL_compat)
movq %rsp, %rdi
call do_fast_syscall_32
- jmp .Lsyscall_32_done
+ testl %eax, %eax
+ jz .Lsyscall_32_done
+
+ /* Opportunistic SYSRET */
+sysret32_from_system_call:
+ TRACE_IRQS_ON /* User mode traces as IRQs on. */
+ movq RBX(%rsp), %rbx /* pt_regs->rbx */
+ movq RBP(%rsp), %rbp /* pt_regs->rbp */
+ movq EFLAGS(%rsp), %r11 /* pt_regs->flags (in r11) */
+ movq RIP(%rsp), %rcx /* pt_regs->ip (in rcx) */
+ addq $RAX, %rsp /* Skip r8-r15 */
+ popq %rax /* pt_regs->rax */
+ popq %rdx /* Skip pt_regs->cx */
+ popq %rdx /* pt_regs->dx */
+ popq %rsi /* pt_regs->si */
+ popq %rdi /* pt_regs->di */
+
+ /*
+ * USERGS_SYSRET32 does:
+ * GSBASE = user's GS base
+ * EIP = ECX
+ * RFLAGS = R11
+ * CS = __USER32_CS
+ * SS = __USER_DS
+ *
+ * ECX will not match pt_regs->cx, but we're returning to a vDSO
+ * trampoline that will fix up RCX, so this is okay.
+ *
+ * R12-R15 are callee-saved, so they contain whatever was in them
+ * when the system call started, which is already known to user
+ * code. We zero R8-R10 to avoid info leaks.
+ */
+ xorq %r8, %r8
+ xorq %r9, %r9
+ xorq %r10, %r10
+ movq RSP-ORIG_RAX(%rsp), %rsp
+ USERGS_SYSRET32
END(entry_SYSCALL_compat)
/*
--
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/
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2015-10-12 18:20 +0200 |
| Subject | Re: [PATCH v2 24/36] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls |
| Message-ID | <qiNZo-48K-13@gated-at.bofh.it> |
| In reply to | #1240063 |
On Mon, Oct 05, 2015 at 05:48:12PM -0700, Andy Lutomirski wrote:
> If CS, SS and IP are as expected and FLAGS is compatible with SYSRETL,
> then return from fast compat syscalls (both SYSCALL and SYSENTER) using
> SYSRETL.
>
> Unlike native 64-bit opportunistic SYSRET, this is not invisible to
> user code: RCX and R8-R15 end up in a different state than shown
> saved in pt_regs. To compensate, we only do this when returning to
> the vDSO fast syscall return path. This won't interfere with
> syscall restart, as we won't use SYSRETL when returning to the INT80
> restart instruction.
>
> Signed-off-by: Andy Lutomirski <luto@kernel.org>
> ---
> arch/x86/entry/common.c | 23 +++++++++++++++++++---
> arch/x86/entry/entry_64_compat.S | 42 ++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 60 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
> index 1b2606edc621..88dc5ba14d47 100644
> --- a/arch/x86/entry/common.c
> +++ b/arch/x86/entry/common.c
> @@ -363,7 +363,8 @@ __visible void do_int80_syscall_32(struct pt_regs *regs)
> syscall_return_slowpath(regs);
> }
>
> -__visible void do_fast_syscall_32(struct pt_regs *regs)
> +/* Returns 0 to return using IRET or 1 to return using SYSRETL. */
> +__visible long do_fast_syscall_32(struct pt_regs *regs)
> {
> /*
> * Called using the internal vDSO SYSENTER/SYSCALL32 calling
> @@ -395,12 +396,28 @@ __visible void do_fast_syscall_32(struct pt_regs *regs)
> enter_from_user_mode();
> #endif
> prepare_exit_to_usermode(regs);
> - return;
> + return 0; /* Keep it simple: use IRET. */
> }
> local_irq_disable();
>
> /* Now this is just like a normal syscall. */
> do_int80_syscall_32(regs);
> - return;
> +
> +#ifdef CONFIG_X86_64
> + /*
> + * Opportunistic SYSRETL: if possible, try to return using SYSRETL.
> + * SYSRETL is available on all 64-bit CPUs, so we don't need to
> + * bother with SYSEXIT.
> + *
> + * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
> + * because the ECX fixup above will ensure that this is essentially
> + * never the case.
> + */
> + return regs->cs == __USER32_CS && regs->ss == __USER_DS &&
> + regs->ip == landing_pad &&
> + (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF)) == 0;
This could've used some readability massaging:
return regs->cs == __USER32_CS &&
regs->ss == __USER_DS &&
regs->ip == landing_pad &&
!(regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF));
Although I'm not crazy about that one either. This expression is simply not
parseable at a glance.
Why not write it like the 64-bit opportunistic SYSRET:
if (regs->cs != __USER32_CS)
return 0;
if (regs->ss != __USER_DS)
return 0;
and so on...
asm is almost the same, except in the "after" case, the CALL to
syscall_trace_enter is after the last JMP.
before:
.L270:
xorl %eax, %eax # D.34060
cmpq $35, 136(%rbx) #, regs_12(D)->cs
je .L296 #,
.L263:
movq -32(%rbp), %rbx #,
movq -24(%rbp), %r12 #,
movq -16(%rbp), %r13 #,
movq -8(%rbp), %r14 #,
leave
ret
.L291:
movq %rbx, %rdi # regs,
call syscall_trace_enter #
jmp .L265 #
.L296:
cmpq $43, 160(%rbx) #, regs_12(D)->ss
jne .L263 #,
cmpq 128(%rbx), %r12 # regs_12(D)->ip, landing_pad
jne .L263 #,
xorl %eax, %eax # D.34060
testq $65792, 144(%rbx) #, regs_12(D)->flags
sete %al #, D.34060
jmp .L263 #
after:
.L271:
cmpq $35, 136(%rbx) #, regs_11(D)->cs
je .L293 #,
.L286:
xorl %eax, %eax # D.34060
.L264:
movq -32(%rbp), %rbx #,
movq -24(%rbp), %r12 #,
movq -16(%rbp), %r13 #,
movq -8(%rbp), %r14 #,
leave
ret
.L293:
cmpq $43, 160(%rbx) #, regs_11(D)->ss
jne .L286 #,
cmpq 128(%rbx), %r12 # regs_11(D)->ip, landing_pad
jne .L286 #,
xorl %eax, %eax # D.34060
testq $65792, 144(%rbx) #, regs_11(D)->flags
sete %al #, D.34060
jmp .L264 #
--
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.
--
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/
[toc] | [prev] | [next] | [standalone]
| From | Andy Lutomirski <luto@amacapital.net> |
|---|---|
| Date | 2015-10-14 18:30 +0200 |
| Subject | Re: [PATCH v2 24/36] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls |
| Message-ID | <qjx6b-3XF-25@gated-at.bofh.it> |
| In reply to | #1244863 |
On Mon, Oct 12, 2015 at 9:15 AM, Borislav Petkov <bp@alien8.de> wrote:
> On Mon, Oct 05, 2015 at 05:48:12PM -0700, Andy Lutomirski wrote:
>> If CS, SS and IP are as expected and FLAGS is compatible with SYSRETL,
>> then return from fast compat syscalls (both SYSCALL and SYSENTER) using
>> SYSRETL.
>>
>> Unlike native 64-bit opportunistic SYSRET, this is not invisible to
>> user code: RCX and R8-R15 end up in a different state than shown
>> saved in pt_regs. To compensate, we only do this when returning to
>> the vDSO fast syscall return path. This won't interfere with
>> syscall restart, as we won't use SYSRETL when returning to the INT80
>> restart instruction.
>>
>> Signed-off-by: Andy Lutomirski <luto@kernel.org>
>> ---
>> arch/x86/entry/common.c | 23 +++++++++++++++++++---
>> arch/x86/entry/entry_64_compat.S | 42 ++++++++++++++++++++++++++++++++++++++--
>> 2 files changed, 60 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
>> index 1b2606edc621..88dc5ba14d47 100644
>> --- a/arch/x86/entry/common.c
>> +++ b/arch/x86/entry/common.c
>> @@ -363,7 +363,8 @@ __visible void do_int80_syscall_32(struct pt_regs *regs)
>> syscall_return_slowpath(regs);
>> }
>>
>> -__visible void do_fast_syscall_32(struct pt_regs *regs)
>> +/* Returns 0 to return using IRET or 1 to return using SYSRETL. */
>> +__visible long do_fast_syscall_32(struct pt_regs *regs)
>> {
>> /*
>> * Called using the internal vDSO SYSENTER/SYSCALL32 calling
>> @@ -395,12 +396,28 @@ __visible void do_fast_syscall_32(struct pt_regs *regs)
>> enter_from_user_mode();
>> #endif
>> prepare_exit_to_usermode(regs);
>> - return;
>> + return 0; /* Keep it simple: use IRET. */
>> }
>> local_irq_disable();
>>
>> /* Now this is just like a normal syscall. */
>> do_int80_syscall_32(regs);
>> - return;
>> +
>> +#ifdef CONFIG_X86_64
>> + /*
>> + * Opportunistic SYSRETL: if possible, try to return using SYSRETL.
>> + * SYSRETL is available on all 64-bit CPUs, so we don't need to
>> + * bother with SYSEXIT.
>> + *
>> + * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
>> + * because the ECX fixup above will ensure that this is essentially
>> + * never the case.
>> + */
>> + return regs->cs == __USER32_CS && regs->ss == __USER_DS &&
>> + regs->ip == landing_pad &&
>> + (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF)) == 0;
>
> This could've used some readability massaging:
>
> return regs->cs == __USER32_CS &&
> regs->ss == __USER_DS &&
> regs->ip == landing_pad &&
> !(regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF));
>
> Although I'm not crazy about that one either. This expression is simply not
> parseable at a glance.
>
> Why not write it like the 64-bit opportunistic SYSRET:
>
> if (regs->cs != __USER32_CS)
> return 0;
>
> if (regs->ss != __USER_DS)
> return 0;
>
> and so on...
We could do that. It might also be nice to factor it into its own function:
static bool may_fast_exit_32(struct pt_regs *regs);
I'll try that eventually if you don't beat me.
--Andy
--
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/
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2015-10-14 18:40 +0200 |
| Subject | Re: [PATCH v2 24/36] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls |
| Message-ID | <qjxfR-493-15@gated-at.bofh.it> |
| In reply to | #1246976 |
On Wed, Oct 14, 2015 at 09:25:24AM -0700, Andy Lutomirski wrote:
> We could do that. It might also be nice to factor it into its own function:
>
> static bool may_fast_exit_32(struct pt_regs *regs);
Right.
> I'll try that eventually if you don't beat me.
I promise I won't beat you! :-P
--
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.
--
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/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web