diff options
author | Jan Kara <jack@suse.cz> | 2014-01-21 18:48:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-21 19:19:41 -0500 |
commit | e9fe69045bd648d75d8d8099b8658a4ee005a8e5 (patch) | |
tree | 9c3e81c861c50df65e3337cbb85af6420a2df47d /fs/notify | |
parent | 0abdd7a81b7e3fd781d7fabcca49501852bba17e (diff) |
inotify: provide function for name length rounding
Rounding of name length when passing it to userspace was done in several
places. Provide a function to do it and use it in all places.
Signed-off-by: Jan Kara <jack@suse.cz>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Cc: Eric Paris <eparis@parisplace.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/notify')
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 60f954a891ab..1bb6dc8eaf1c 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -124,6 +124,13 @@ static unsigned int inotify_poll(struct file *file, poll_table *wait) | |||
124 | return ret; | 124 | return ret; |
125 | } | 125 | } |
126 | 126 | ||
127 | static int round_event_name_len(struct fsnotify_event *event) | ||
128 | { | ||
129 | if (!event->name_len) | ||
130 | return 0; | ||
131 | return roundup(event->name_len + 1, sizeof(struct inotify_event)); | ||
132 | } | ||
133 | |||
127 | /* | 134 | /* |
128 | * Get an inotify_kernel_event if one exists and is small | 135 | * Get an inotify_kernel_event if one exists and is small |
129 | * enough to fit in "count". Return an error pointer if | 136 | * enough to fit in "count". Return an error pointer if |
@@ -144,9 +151,7 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group, | |||
144 | 151 | ||
145 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); | 152 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); |
146 | 153 | ||
147 | if (event->name_len) | 154 | event_size += round_event_name_len(event); |
148 | event_size += roundup(event->name_len + 1, event_size); | ||
149 | |||
150 | if (event_size > count) | 155 | if (event_size > count) |
151 | return ERR_PTR(-EINVAL); | 156 | return ERR_PTR(-EINVAL); |
152 | 157 | ||
@@ -171,7 +176,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, | |||
171 | struct fsnotify_event_private_data *fsn_priv; | 176 | struct fsnotify_event_private_data *fsn_priv; |
172 | struct inotify_event_private_data *priv; | 177 | struct inotify_event_private_data *priv; |
173 | size_t event_size = sizeof(struct inotify_event); | 178 | size_t event_size = sizeof(struct inotify_event); |
174 | size_t name_len = 0; | 179 | size_t name_len; |
180 | size_t pad_name_len; | ||
175 | 181 | ||
176 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); | 182 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); |
177 | 183 | ||
@@ -189,14 +195,13 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, | |||
189 | inotify_free_event_priv(fsn_priv); | 195 | inotify_free_event_priv(fsn_priv); |
190 | } | 196 | } |
191 | 197 | ||
198 | name_len = event->name_len; | ||
192 | /* | 199 | /* |
193 | * round up event->name_len so it is a multiple of event_size | 200 | * round up name length so it is a multiple of event_size |
194 | * plus an extra byte for the terminating '\0'. | 201 | * plus an extra byte for the terminating '\0'. |
195 | */ | 202 | */ |
196 | if (event->name_len) | 203 | pad_name_len = round_event_name_len(event); |
197 | name_len = roundup(event->name_len + 1, event_size); | 204 | inotify_event.len = pad_name_len; |
198 | inotify_event.len = name_len; | ||
199 | |||
200 | inotify_event.mask = inotify_mask_to_arg(event->mask); | 205 | inotify_event.mask = inotify_mask_to_arg(event->mask); |
201 | inotify_event.cookie = event->sync_cookie; | 206 | inotify_event.cookie = event->sync_cookie; |
202 | 207 | ||
@@ -209,20 +214,18 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, | |||
209 | /* | 214 | /* |
210 | * fsnotify only stores the pathname, so here we have to send the pathname | 215 | * fsnotify only stores the pathname, so here we have to send the pathname |
211 | * and then pad that pathname out to a multiple of sizeof(inotify_event) | 216 | * and then pad that pathname out to a multiple of sizeof(inotify_event) |
212 | * with zeros. I get my zeros from the nul_inotify_event. | 217 | * with zeros. |
213 | */ | 218 | */ |
214 | if (name_len) { | 219 | if (pad_name_len) { |
215 | unsigned int len_to_zero = name_len - event->name_len; | ||
216 | /* copy the path name */ | 220 | /* copy the path name */ |
217 | if (copy_to_user(buf, event->file_name, event->name_len)) | 221 | if (copy_to_user(buf, event->file_name, name_len)) |
218 | return -EFAULT; | 222 | return -EFAULT; |
219 | buf += event->name_len; | 223 | buf += name_len; |
220 | 224 | ||
221 | /* fill userspace with 0's */ | 225 | /* fill userspace with 0's */ |
222 | if (clear_user(buf, len_to_zero)) | 226 | if (clear_user(buf, pad_name_len - name_len)) |
223 | return -EFAULT; | 227 | return -EFAULT; |
224 | buf += len_to_zero; | 228 | event_size += pad_name_len; |
225 | event_size += name_len; | ||
226 | } | 229 | } |
227 | 230 | ||
228 | return event_size; | 231 | return event_size; |
@@ -314,9 +317,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd, | |||
314 | list_for_each_entry(holder, &group->notification_list, event_list) { | 317 | list_for_each_entry(holder, &group->notification_list, event_list) { |
315 | event = holder->event; | 318 | event = holder->event; |
316 | send_len += sizeof(struct inotify_event); | 319 | send_len += sizeof(struct inotify_event); |
317 | if (event->name_len) | 320 | send_len += round_event_name_len(event); |
318 | send_len += roundup(event->name_len + 1, | ||
319 | sizeof(struct inotify_event)); | ||
320 | } | 321 | } |
321 | mutex_unlock(&group->notification_mutex); | 322 | mutex_unlock(&group->notification_mutex); |
322 | ret = put_user(send_len, (int __user *) p); | 323 | ret = put_user(send_len, (int __user *) p); |