* [PATCH 1/3] bpf: Don't check for current being NULL
@ 2017-10-16 18:18 Richard Weinberger
2017-10-16 18:18 ` [PATCH 2/3] bpf: Remove dead variable Richard Weinberger
2017-10-16 18:18 ` [PATCH 3/3] bpf: Make sure that ->comm does not change under us Richard Weinberger
0 siblings, 2 replies; 14+ messages in thread
From: Richard Weinberger @ 2017-10-16 18:18 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, daniel, ast, Richard Weinberger
current is never NULL.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
kernel/bpf/helpers.c | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 3d24e238221e..e8845adcd15e 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -120,9 +120,6 @@ BPF_CALL_0(bpf_get_current_pid_tgid)
{
struct task_struct *task = current;
- if (unlikely(!task))
- return -EINVAL;
-
return (u64) task->tgid << 32 | task->pid;
}
@@ -138,9 +135,6 @@ BPF_CALL_0(bpf_get_current_uid_gid)
kuid_t uid;
kgid_t gid;
- if (unlikely(!task))
- return -EINVAL;
-
current_uid_gid(&uid, &gid);
return (u64) from_kgid(&init_user_ns, gid) << 32 |
from_kuid(&init_user_ns, uid);
@@ -156,9 +150,6 @@ BPF_CALL_2(bpf_get_current_comm, char *, buf, u32, size)
{
struct task_struct *task = current;
- if (unlikely(!task))
- goto err_clear;
-
strncpy(buf, task->comm, size);
/* Verifier guarantees that size > 0. For task->comm exceeding
@@ -167,9 +158,6 @@ BPF_CALL_2(bpf_get_current_comm, char *, buf, u32, size)
*/
buf[size - 1] = 0;
return 0;
-err_clear:
- memset(buf, 0, size);
- return -EINVAL;
}
const struct bpf_func_proto bpf_get_current_comm_proto = {
--
2.13.6
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/3] bpf: Remove dead variable
2017-10-16 18:18 [PATCH 1/3] bpf: Don't check for current being NULL Richard Weinberger
@ 2017-10-16 18:18 ` Richard Weinberger
2017-10-16 18:54 ` Daniel Borkmann
2017-10-16 18:18 ` [PATCH 3/3] bpf: Make sure that ->comm does not change under us Richard Weinberger
1 sibling, 1 reply; 14+ messages in thread
From: Richard Weinberger @ 2017-10-16 18:18 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, daniel, ast, Richard Weinberger
task is never used in bpf_get_current_uid_gid(), kill it.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
kernel/bpf/helpers.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index e8845adcd15e..511c9d522cfc 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -131,7 +131,6 @@ const struct bpf_func_proto bpf_get_current_pid_tgid_proto = {
BPF_CALL_0(bpf_get_current_uid_gid)
{
- struct task_struct *task = current;
kuid_t uid;
kgid_t gid;
--
2.13.6
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
2017-10-16 18:18 [PATCH 1/3] bpf: Don't check for current being NULL Richard Weinberger
2017-10-16 18:18 ` [PATCH 2/3] bpf: Remove dead variable Richard Weinberger
@ 2017-10-16 18:18 ` Richard Weinberger
2017-10-16 20:50 ` Daniel Borkmann
1 sibling, 1 reply; 14+ messages in thread
From: Richard Weinberger @ 2017-10-16 18:18 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, daniel, ast, Richard Weinberger
Sadly we cannot use get_task_comm() since bpf_get_current_comm()
allows truncation.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
kernel/bpf/helpers.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 511c9d522cfc..4b042b24524d 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <linux/uidgid.h>
#include <linux/filter.h>
+#include <linux/sched/task.h>
/* If kernel subsystem is allowing eBPF programs to call this function,
* inside its own verifier_ops->get_func_proto() callback it should return
@@ -149,7 +150,9 @@ BPF_CALL_2(bpf_get_current_comm, char *, buf, u32, size)
{
struct task_struct *task = current;
+ task_lock(task);
strncpy(buf, task->comm, size);
+ task_unlock(task);
/* Verifier guarantees that size > 0. For task->comm exceeding
* size, guarantee that buf is %NUL-terminated. Unconditionally
--
2.13.6
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] bpf: Remove dead variable
2017-10-16 18:18 ` [PATCH 2/3] bpf: Remove dead variable Richard Weinberger
@ 2017-10-16 18:54 ` Daniel Borkmann
2017-10-16 18:59 ` Richard Weinberger
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Borkmann @ 2017-10-16 18:54 UTC (permalink / raw)
To: Richard Weinberger, netdev; +Cc: linux-kernel, ast
On 10/16/2017 08:18 PM, Richard Weinberger wrote:
> task is never used in bpf_get_current_uid_gid(), kill it.
>
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
> kernel/bpf/helpers.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index e8845adcd15e..511c9d522cfc 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -131,7 +131,6 @@ const struct bpf_func_proto bpf_get_current_pid_tgid_proto = {
>
> BPF_CALL_0(bpf_get_current_uid_gid)
> {
> - struct task_struct *task = current;
> kuid_t uid;
> kgid_t gid;
>
>
Needs to be squashed into patch 1/3?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] bpf: Remove dead variable
2017-10-16 18:54 ` Daniel Borkmann
@ 2017-10-16 18:59 ` Richard Weinberger
2017-10-16 19:11 ` Daniel Borkmann
0 siblings, 1 reply; 14+ messages in thread
From: Richard Weinberger @ 2017-10-16 18:59 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: netdev, linux-kernel, ast
Am Montag, 16. Oktober 2017, 20:54:36 CEST schrieb Daniel Borkmann:
> On 10/16/2017 08:18 PM, Richard Weinberger wrote:
> > task is never used in bpf_get_current_uid_gid(), kill it.
> >
> > Signed-off-by: Richard Weinberger <richard@nod.at>
> > ---
> >
> > kernel/bpf/helpers.c | 1 -
> > 1 file changed, 1 deletion(-)
> >
> > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> > index e8845adcd15e..511c9d522cfc 100644
> > --- a/kernel/bpf/helpers.c
> > +++ b/kernel/bpf/helpers.c
> > @@ -131,7 +131,6 @@ const struct bpf_func_proto
> > bpf_get_current_pid_tgid_proto = {>
> > BPF_CALL_0(bpf_get_current_uid_gid)
> > {
> >
> > - struct task_struct *task = current;
> >
> > kuid_t uid;
> > kgid_t gid;
>
> Needs to be squashed into patch 1/3?
I can squash it into 1/3, I kept it that way because
even without 1/3 this variable is unused.
Thanks,
//richard
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] bpf: Remove dead variable
2017-10-16 18:59 ` Richard Weinberger
@ 2017-10-16 19:11 ` Daniel Borkmann
2017-10-16 19:22 ` Richard Weinberger
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Borkmann @ 2017-10-16 19:11 UTC (permalink / raw)
To: Richard Weinberger; +Cc: netdev, linux-kernel, ast
On 10/16/2017 08:59 PM, Richard Weinberger wrote:
> Am Montag, 16. Oktober 2017, 20:54:36 CEST schrieb Daniel Borkmann:
>> On 10/16/2017 08:18 PM, Richard Weinberger wrote:
>>> task is never used in bpf_get_current_uid_gid(), kill it.
>>>
>>> Signed-off-by: Richard Weinberger <richard@nod.at>
>>> ---
>>>
>>> kernel/bpf/helpers.c | 1 -
>>> 1 file changed, 1 deletion(-)
>>>
>>> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
>>> index e8845adcd15e..511c9d522cfc 100644
>>> --- a/kernel/bpf/helpers.c
>>> +++ b/kernel/bpf/helpers.c
>>> @@ -131,7 +131,6 @@ const struct bpf_func_proto
>>> bpf_get_current_pid_tgid_proto = {>
>>> BPF_CALL_0(bpf_get_current_uid_gid)
>>> {
>>>
>>> - struct task_struct *task = current;
>>>
>>> kuid_t uid;
>>> kgid_t gid;
>>
>> Needs to be squashed into patch 1/3?
>
> I can squash it into 1/3, I kept it that way because
> even without 1/3 this variable is unused.
Hmm, the helper looks like the below. In patch 1/3 you removed
the 'if (unlikely(!task))' test where the variable was used before,
so 2/3 without the 1/3 would result in a compile error.
BPF_CALL_0(bpf_get_current_uid_gid)
{
struct task_struct *task = current;
kuid_t uid;
kgid_t gid;
if (unlikely(!task))
return -EINVAL;
current_uid_gid(&uid, &gid);
return (u64) from_kgid(&init_user_ns, gid) << 32 |
from_kuid(&init_user_ns, uid);
}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] bpf: Remove dead variable
2017-10-16 19:11 ` Daniel Borkmann
@ 2017-10-16 19:22 ` Richard Weinberger
2017-10-16 20:48 ` Daniel Borkmann
0 siblings, 1 reply; 14+ messages in thread
From: Richard Weinberger @ 2017-10-16 19:22 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: netdev, linux-kernel, ast
Am Montag, 16. Oktober 2017, 21:11:47 CEST schrieb Daniel Borkmann:
> > I can squash it into 1/3, I kept it that way because
> > even without 1/3 this variable is unused.
>
> Hmm, the helper looks like the below. In patch 1/3 you removed
> the 'if (unlikely(!task))' test where the variable was used before,
> so 2/3 without the 1/3 would result in a compile error.
Why a compile error? It emits a warning.
> BPF_CALL_0(bpf_get_current_uid_gid)
> {
> struct task_struct *task = current;
> kuid_t uid;
> kgid_t gid;
>
> if (unlikely(!task))
> return -EINVAL;
Well, this is the only "user". Okay.
> current_uid_gid(&uid, &gid);
Here we use current. So, task was always in vain.
So, I can happily squash 2/3 into 1/3 and resent.
The series just represented the way I've worked on the code...
Thanks,
//richard
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] bpf: Remove dead variable
2017-10-16 19:22 ` Richard Weinberger
@ 2017-10-16 20:48 ` Daniel Borkmann
0 siblings, 0 replies; 14+ messages in thread
From: Daniel Borkmann @ 2017-10-16 20:48 UTC (permalink / raw)
To: Richard Weinberger; +Cc: netdev, linux-kernel, ast
On 10/16/2017 09:22 PM, Richard Weinberger wrote:
[...]
> So, I can happily squash 2/3 into 1/3 and resent.
Yeah, please just squash them.
Thanks,
Daniel
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
2017-10-16 18:18 ` [PATCH 3/3] bpf: Make sure that ->comm does not change under us Richard Weinberger
@ 2017-10-16 20:50 ` Daniel Borkmann
2017-10-16 20:55 ` Richard Weinberger
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Borkmann @ 2017-10-16 20:50 UTC (permalink / raw)
To: Richard Weinberger, netdev; +Cc: linux-kernel, ast
On 10/16/2017 08:18 PM, Richard Weinberger wrote:
> Sadly we cannot use get_task_comm() since bpf_get_current_comm()
> allows truncation.
>
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
> kernel/bpf/helpers.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index 511c9d522cfc..4b042b24524d 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -18,6 +18,7 @@
> #include <linux/sched.h>
> #include <linux/uidgid.h>
> #include <linux/filter.h>
> +#include <linux/sched/task.h>
>
> /* If kernel subsystem is allowing eBPF programs to call this function,
> * inside its own verifier_ops->get_func_proto() callback it should return
> @@ -149,7 +150,9 @@ BPF_CALL_2(bpf_get_current_comm, char *, buf, u32, size)
> {
> struct task_struct *task = current;
>
> + task_lock(task);
> strncpy(buf, task->comm, size);
> + task_unlock(task);
Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
bpf_get_current_comm() taking the lock again ...
> /* Verifier guarantees that size > 0. For task->comm exceeding
> * size, guarantee that buf is %NUL-terminated. Unconditionally
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
2017-10-16 20:50 ` Daniel Borkmann
@ 2017-10-16 20:55 ` Richard Weinberger
2017-10-16 21:02 ` Daniel Borkmann
0 siblings, 1 reply; 14+ messages in thread
From: Richard Weinberger @ 2017-10-16 20:55 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: netdev, linux-kernel, ast
Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
> > struct task_struct *task = current;
> >
> > + task_lock(task);
> >
> > strncpy(buf, task->comm, size);
> >
> > + task_unlock(task);
>
> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
> bpf_get_current_comm() taking the lock again ...
Yes, but doesn't the same apply to the use case when I attach to strncpy()
and run bpf_get_current_comm()?
Thanks,
//richard
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
2017-10-16 20:55 ` Richard Weinberger
@ 2017-10-16 21:02 ` Daniel Borkmann
2017-10-16 21:10 ` Richard Weinberger
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Borkmann @ 2017-10-16 21:02 UTC (permalink / raw)
To: Richard Weinberger; +Cc: netdev, linux-kernel, ast
On 10/16/2017 10:55 PM, Richard Weinberger wrote:
> Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
>>> struct task_struct *task = current;
>>>
>>> + task_lock(task);
>>>
>>> strncpy(buf, task->comm, size);
>>>
>>> + task_unlock(task);
>>
>> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
>> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
>> bpf_get_current_comm() taking the lock again ...
>
> Yes, but doesn't the same apply to the use case when I attach to strncpy()
> and run bpf_get_current_comm()?
You mean due to recursion? In that case trace_call_bpf() would bail out
due to the bpf_prog_active counter.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
2017-10-16 21:02 ` Daniel Borkmann
@ 2017-10-16 21:10 ` Richard Weinberger
0 siblings, 0 replies; 14+ messages in thread
From: Richard Weinberger @ 2017-10-16 21:10 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: netdev, linux-kernel, ast
Am Montag, 16. Oktober 2017, 23:02:06 CEST schrieb Daniel Borkmann:
> On 10/16/2017 10:55 PM, Richard Weinberger wrote:
> > Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
> >>> struct task_struct *task = current;
> >>>
> >>> + task_lock(task);
> >>>
> >>> strncpy(buf, task->comm, size);
> >>>
> >>> + task_unlock(task);
> >>
> >> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
> >> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
> >> bpf_get_current_comm() taking the lock again ...
> >
> > Yes, but doesn't the same apply to the use case when I attach to strncpy()
> > and run bpf_get_current_comm()?
>
> You mean due to recursion? In that case trace_call_bpf() would bail out
> due to the bpf_prog_active counter.
Ah, that's true.
So, when someone wants to use bpf_get_current_comm() while tracing task_lock,
we have a problem. I agree.
On the other hand, without locking the function may return wrong results.
Thanks,
//richard
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
@ 2017-10-16 22:10 Alexei Starovoitov
2017-10-16 22:19 ` Daniel Borkmann
0 siblings, 1 reply; 14+ messages in thread
From: Alexei Starovoitov @ 2017-10-16 22:10 UTC (permalink / raw)
To: Richard Weinberger
Cc: Daniel Borkmann, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, Alexei Starovoitov
On Mon, Oct 16, 2017 at 2:10 PM, Richard Weinberger <richard@nod.at> wrote:
> Am Montag, 16. Oktober 2017, 23:02:06 CEST schrieb Daniel Borkmann:
>> On 10/16/2017 10:55 PM, Richard Weinberger wrote:
>> > Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
>> >>> struct task_struct *task = current;
>> >>>
>> >>> + task_lock(task);
>> >>>
>> >>> strncpy(buf, task->comm, size);
>> >>>
>> >>> + task_unlock(task);
>> >>
>> >> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
>> >> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
>> >> bpf_get_current_comm() taking the lock again ...
>> >
>> > Yes, but doesn't the same apply to the use case when I attach to strncpy()
>> > and run bpf_get_current_comm()?
>>
>> You mean due to recursion? In that case trace_call_bpf() would bail out
>> due to the bpf_prog_active counter.
>
> Ah, that's true.
> So, when someone wants to use bpf_get_current_comm() while tracing task_lock,
> we have a problem. I agree.
> On the other hand, without locking the function may return wrong results.
it will surely race with somebody else setting task comm and it's fine.
all of bpf tracing is read-only, so locks are only allowed inside bpf core
bits like maps. Taking core locks like task_lock() is quite scary.
bpf scripts rely on bpf_probe_read() of all sorts of kernel fields
so reading comm here w/o lock is fine.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
2017-10-16 22:10 Alexei Starovoitov
@ 2017-10-16 22:19 ` Daniel Borkmann
0 siblings, 0 replies; 14+ messages in thread
From: Daniel Borkmann @ 2017-10-16 22:19 UTC (permalink / raw)
To: Alexei Starovoitov, Richard Weinberger
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
Alexei Starovoitov
On 10/17/2017 12:10 AM, Alexei Starovoitov wrote:
> On Mon, Oct 16, 2017 at 2:10 PM, Richard Weinberger <richard@nod.at> wrote:
>> Am Montag, 16. Oktober 2017, 23:02:06 CEST schrieb Daniel Borkmann:
>>> On 10/16/2017 10:55 PM, Richard Weinberger wrote:
>>>> Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
>>>>>> struct task_struct *task = current;
>>>>>>
>>>>>> + task_lock(task);
>>>>>>
>>>>>> strncpy(buf, task->comm, size);
>>>>>>
>>>>>> + task_unlock(task);
>>>>>
>>>>> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
>>>>> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
>>>>> bpf_get_current_comm() taking the lock again ...
>>>>
>>>> Yes, but doesn't the same apply to the use case when I attach to strncpy()
>>>> and run bpf_get_current_comm()?
>>>
>>> You mean due to recursion? In that case trace_call_bpf() would bail out
>>> due to the bpf_prog_active counter.
>>
>> Ah, that's true.
>> So, when someone wants to use bpf_get_current_comm() while tracing task_lock,
>> we have a problem. I agree.
>> On the other hand, without locking the function may return wrong results.
>
> it will surely race with somebody else setting task comm and it's fine.
> all of bpf tracing is read-only, so locks are only allowed inside bpf core
> bits like maps. Taking core locks like task_lock() is quite scary.
> bpf scripts rely on bpf_probe_read() of all sorts of kernel fields
> so reading comm here w/o lock is fine.
Yeah, and perf_event_comm() -> perf_event_comm_event() out of __set_task_comm()
is having same approach wrt comm read-out.
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2017-10-16 22:19 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-16 18:18 [PATCH 1/3] bpf: Don't check for current being NULL Richard Weinberger
2017-10-16 18:18 ` [PATCH 2/3] bpf: Remove dead variable Richard Weinberger
2017-10-16 18:54 ` Daniel Borkmann
2017-10-16 18:59 ` Richard Weinberger
2017-10-16 19:11 ` Daniel Borkmann
2017-10-16 19:22 ` Richard Weinberger
2017-10-16 20:48 ` Daniel Borkmann
2017-10-16 18:18 ` [PATCH 3/3] bpf: Make sure that ->comm does not change under us Richard Weinberger
2017-10-16 20:50 ` Daniel Borkmann
2017-10-16 20:55 ` Richard Weinberger
2017-10-16 21:02 ` Daniel Borkmann
2017-10-16 21:10 ` Richard Weinberger
-- strict thread matches above, loose matches on Subject: below --
2017-10-16 22:10 Alexei Starovoitov
2017-10-16 22:19 ` Daniel Borkmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).