File handles can be requested to send sigio and sigurg
to processes. This code modifies the code to track
those processes making the interface safe from pid
wrap around issues.
It's not a big deal deal but since it is easy to track
the proceses we might as well.
Signed-off-by: Eric W. Biederman <[email protected]>
---
fs/fcntl.c | 45 ++++++++++++++++++++++++---------------------
fs/file_table.c | 1 +
include/linux/fs.h | 1 +
net/socket.c | 5 ++++-
4 files changed, 30 insertions(+), 22 deletions(-)
4c0475dcf7c47c1590c5d7dd06c28a457ebabe33
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 5f96786..af1b02a 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -251,8 +251,17 @@ static int setfl(int fd, struct file * f
static void f_modown(struct file *filp, unsigned long pid,
uid_t uid, uid_t euid, int force)
{
+
+ enum pid_type type;
+ int who = pid;
+ type = PIDTYPE_PID;
+ if (who < 0) {
+ type = PIDTYPE_PGID;
+ who = -who;
+ }
write_lock_irq(&filp->f_owner.lock);
if (force || !filp->f_owner.pid) {
+ tref_set(&filp->f_owner.tref, tref_get_by_pid(who, type));
filp->f_owner.pid = pid;
filp->f_owner.uid = uid;
filp->f_owner.euid = euid;
@@ -317,7 +326,9 @@ static long do_fcntl(int fd, unsigned in
* current syscall conventions, the only way
* to fix this will be in libc.
*/
- err = filp->f_owner.pid;
+ err = 0;
+ if (filp->f_owner.tref->task)
+ err = filp->f_owner.pid;
force_successful_syscall_return();
break;
case F_SETOWN:
@@ -469,6 +480,7 @@ static void send_sigio_to_task(struct ta
void send_sigio(struct fown_struct *fown, int fd, int band)
{
struct task_struct *p;
+ enum pid_type type;
int pid;
read_lock(&fown->lock);
@@ -477,16 +489,11 @@ void send_sigio(struct fown_struct *fown
goto out_unlock_fown;
read_lock(&tasklist_lock);
- if (pid > 0) {
- p = find_task_by_pid(pid);
- if (p) {
- send_sigio_to_task(p, fown, fd, band);
- }
- } else {
- do_each_task_pid(-pid, PIDTYPE_PGID, p) {
- send_sigio_to_task(p, fown, fd, band);
- } while_each_task_pid(-pid, PIDTYPE_PGID, p);
- }
+ type = fown->tref->type;
+ p = fown->tref->task;
+ do_each_task(p, type) {
+ send_sigio_to_task(p, fown, fd, band);
+ } while_each_task(p, type);
read_unlock(&tasklist_lock);
out_unlock_fown:
read_unlock(&fown->lock);
@@ -503,6 +510,7 @@ int send_sigurg(struct fown_struct *fown
{
struct task_struct *p;
int pid, ret = 0;
+ enum pid_type type;
read_lock(&fown->lock);
pid = fown->pid;
@@ -512,16 +520,11 @@ int send_sigurg(struct fown_struct *fown
ret = 1;
read_lock(&tasklist_lock);
- if (pid > 0) {
- p = find_task_by_pid(pid);
- if (p) {
- send_sigurg_to_task(p, fown);
- }
- } else {
- do_each_task_pid(-pid, PIDTYPE_PGID, p) {
- send_sigurg_to_task(p, fown);
- } while_each_task_pid(-pid, PIDTYPE_PGID, p);
- }
+ type = fown->tref->type;
+ p = fown->tref->task;
+ do_each_task(p, type) {
+ send_sigurg_to_task(p, fown);
+ } while_each_task(p, type);
read_unlock(&tasklist_lock);
out_unlock_fown:
read_unlock(&fown->lock);
diff --git a/fs/file_table.c b/fs/file_table.c
index 768b581..fb70a30 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -97,6 +97,7 @@ struct file *get_empty_filp(void)
rwlock_init(&f->f_owner.lock);
/* f->f_version: 0 */
INIT_LIST_HEAD(&f->f_u.fu_list);
+ f->f_owner.tref = &init_tref;
return f;
over:
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 84bb449..35449c2 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -587,6 +587,7 @@ extern struct block_device *I_BDEV(struc
struct fown_struct {
rwlock_t lock; /* protects pid, uid, euid fields */
+ struct task_ref *tref; /* Reference to the task/process group */
int pid; /* pid or -pgrp where SIGIO should be sent */
uid_t uid, euid; /* uid/euid of process setting the owner */
void *security;
diff --git a/net/socket.c b/net/socket.c
index b38a263..4294a77 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -855,7 +855,10 @@ static long sock_ioctl(struct file *file
break;
case FIOGETOWN:
case SIOCGPGRP:
- err = put_user(sock->file->f_owner.pid, (int __user *)argp);
+ pid = 0;
+ if (sock->file->f_owner.tref->task)
+ pid = sock->file->f_owner.pid;
+ err = put_user(pid, (int __user *)argp);
break;
case SIOCGIFBR:
case SIOCSIFBR:
--
1.1.5.g3480
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]