Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0097875b authored by Eric W. Biederman's avatar Eric W. Biederman
Browse files

proc: Implement /proc/thread-self to point at the directory of the current thread



/proc/thread-self is derived from /proc/self.  /proc/thread-self
points to the directory in proc containing information about the
current thread.

This funtionality has been missing for a long time, and is tricky to
implement in userspace as gettid() is not exported by glibc.  More
importantly this allows fixing defects in /proc/mounts and /proc/net
where in a threaded application today they wind up being empty files
when only the initial pthread has exited, causing problems for other
threads.

Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
parent 6ba8ed79
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ proc-y += version.o
proc-y	+= softirqs.o
proc-y	+= namespaces.o
proc-y	+= self.o
proc-y	+= thread_self.o
proc-$(CONFIG_PROC_SYSCTL)	+= proc_sysctl.o
proc-$(CONFIG_NET)		+= proc_net.o
proc-$(CONFIG_PROC_KCORE)	+= kcore.o
+10 −5
Original line number Diff line number Diff line
@@ -2847,7 +2847,7 @@ static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter ite
	return iter;
}

#define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1)
#define TGID_OFFSET (FIRST_PROCESS_ENTRY + 2)

/* for the /proc/ directory itself, after non-process stuff has been done */
int proc_pid_readdir(struct file *file, struct dir_context *ctx)
@@ -2859,14 +2859,19 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
	if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
		return 0;

	if (pos == TGID_OFFSET - 1) {
	if (pos == TGID_OFFSET - 2) {
		struct inode *inode = ns->proc_self->d_inode;
		if (!dir_emit(ctx, "self", 4, inode->i_ino, DT_LNK))
			return 0;
		iter.tgid = 0;
	} else {
		iter.tgid = pos - TGID_OFFSET;
		ctx->pos = pos = pos + 1;
	}
	if (pos == TGID_OFFSET - 1) {
		struct inode *inode = ns->proc_thread_self->d_inode;
		if (!dir_emit(ctx, "thread-self", 11, inode->i_ino, DT_LNK))
			return 0;
		ctx->pos = pos = pos + 1;
	}
	iter.tgid = pos - TGID_OFFSET;
	iter.task = NULL;
	for (iter = next_tgid(ns, iter);
	     iter.task;
+6 −1
Original line number Diff line number Diff line
@@ -442,6 +442,7 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
int proc_fill_super(struct super_block *s)
{
	struct inode *root_inode;
	int ret;

	s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
	s->s_blocksize = 1024;
@@ -463,5 +464,9 @@ int proc_fill_super(struct super_block *s)
		return -ENOMEM;
	}

	return proc_setup_self(s);
	ret = proc_setup_self(s);
	if (ret) {
		return ret;
	}
	return proc_setup_thread_self(s);
}
+6 −0
Original line number Diff line number Diff line
@@ -233,6 +233,12 @@ static inline int proc_net_init(void) { return 0; }
 */
extern int proc_setup_self(struct super_block *);

/*
 * proc_thread_self.c
 */
extern int proc_setup_thread_self(struct super_block *);
extern void proc_thread_self_init(void);

/*
 * proc_sysctl.c
 */
+3 −0
Original line number Diff line number Diff line
@@ -149,6 +149,8 @@ static void proc_kill_sb(struct super_block *sb)
	ns = (struct pid_namespace *)sb->s_fs_info;
	if (ns->proc_self)
		dput(ns->proc_self);
	if (ns->proc_thread_self)
		dput(ns->proc_thread_self);
	kill_anon_super(sb);
	put_pid_ns(ns);
}
@@ -170,6 +172,7 @@ void __init proc_root_init(void)
		return;

	proc_self_init();
	proc_thread_self_init();
	proc_symlink("mounts", NULL, "self/mounts");

	proc_net_init();
Loading