diff options
| -rw-r--r-- | include/linux/sched.h | 2 | ||||
| -rw-r--r-- | include/net/scm.h | 5 | ||||
| -rw-r--r-- | net/core/scm.c | 24 |
3 files changed, 26 insertions, 5 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index b483f39a7112..295b7c756ca6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1349,6 +1349,8 @@ struct task_struct { | |||
| 1349 | */ | 1349 | */ |
| 1350 | unsigned long timer_slack_ns; | 1350 | unsigned long timer_slack_ns; |
| 1351 | unsigned long default_timer_slack_ns; | 1351 | unsigned long default_timer_slack_ns; |
| 1352 | |||
| 1353 | struct list_head *scm_work_list; | ||
| 1352 | }; | 1354 | }; |
| 1353 | 1355 | ||
| 1354 | /* | 1356 | /* |
diff --git a/include/net/scm.h b/include/net/scm.h index 06df126103ca..33e9986beb86 100644 --- a/include/net/scm.h +++ b/include/net/scm.h | |||
| @@ -14,8 +14,9 @@ | |||
| 14 | 14 | ||
| 15 | struct scm_fp_list | 15 | struct scm_fp_list |
| 16 | { | 16 | { |
| 17 | int count; | 17 | struct list_head list; |
| 18 | struct file *fp[SCM_MAX_FD]; | 18 | int count; |
| 19 | struct file *fp[SCM_MAX_FD]; | ||
| 19 | }; | 20 | }; |
| 20 | 21 | ||
| 21 | struct scm_cookie | 22 | struct scm_cookie |
diff --git a/net/core/scm.c b/net/core/scm.c index 10f5c65f6a47..ab242cc1acca 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
| @@ -75,6 +75,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) | |||
| 75 | if (!fpl) | 75 | if (!fpl) |
| 76 | return -ENOMEM; | 76 | return -ENOMEM; |
| 77 | *fplp = fpl; | 77 | *fplp = fpl; |
| 78 | INIT_LIST_HEAD(&fpl->list); | ||
| 78 | fpl->count = 0; | 79 | fpl->count = 0; |
| 79 | } | 80 | } |
| 80 | fpp = &fpl->fp[fpl->count]; | 81 | fpp = &fpl->fp[fpl->count]; |
| @@ -106,9 +107,25 @@ void __scm_destroy(struct scm_cookie *scm) | |||
| 106 | 107 | ||
| 107 | if (fpl) { | 108 | if (fpl) { |
| 108 | scm->fp = NULL; | 109 | scm->fp = NULL; |
| 109 | for (i=fpl->count-1; i>=0; i--) | 110 | if (current->scm_work_list) { |
| 110 | fput(fpl->fp[i]); | 111 | list_add_tail(&fpl->list, current->scm_work_list); |
| 111 | kfree(fpl); | 112 | } else { |
| 113 | LIST_HEAD(work_list); | ||
| 114 | |||
| 115 | current->scm_work_list = &work_list; | ||
| 116 | |||
| 117 | list_add(&fpl->list, &work_list); | ||
| 118 | while (!list_empty(&work_list)) { | ||
| 119 | fpl = list_first_entry(&work_list, struct scm_fp_list, list); | ||
| 120 | |||
| 121 | list_del(&fpl->list); | ||
| 122 | for (i=fpl->count-1; i>=0; i--) | ||
| 123 | fput(fpl->fp[i]); | ||
| 124 | kfree(fpl); | ||
| 125 | } | ||
| 126 | |||
| 127 | current->scm_work_list = NULL; | ||
| 128 | } | ||
| 112 | } | 129 | } |
| 113 | } | 130 | } |
| 114 | 131 | ||
| @@ -284,6 +301,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) | |||
| 284 | 301 | ||
| 285 | new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); | 302 | new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); |
| 286 | if (new_fpl) { | 303 | if (new_fpl) { |
| 304 | INIT_LIST_HEAD(&new_fpl->list); | ||
| 287 | for (i=fpl->count-1; i>=0; i--) | 305 | for (i=fpl->count-1; i>=0; i--) |
| 288 | get_file(fpl->fp[i]); | 306 | get_file(fpl->fp[i]); |
| 289 | memcpy(new_fpl, fpl, sizeof(*fpl)); | 307 | memcpy(new_fpl, fpl, sizeof(*fpl)); |
