Commit 33a464c4 authored by Kirill Tkhai's avatar Kirill Tkhai Committed by Pavel Emelyanov

files: Fix find_unused_fd() overflow

This function may catch overflow near INT_MAX, so
it becomes return strange fd, like fd = -2147483648.
Fix that.
Signed-off-by: 's avatarKirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 68a938ea
...@@ -97,6 +97,31 @@ static inline struct file_desc *find_file_desc(FdinfoEntry *fe) ...@@ -97,6 +97,31 @@ static inline struct file_desc *find_file_desc(FdinfoEntry *fe)
return find_file_desc_raw(fe->type, fe->id); return find_file_desc_raw(fe->type, fe->id);
} }
unsigned int find_unused_fd(struct list_head *head, int hint_fd)
{
struct fdinfo_list_entry *fle;
int fd = 0, prev_fd;
if ((hint_fd >= 0) && (!fd_is_used(head, hint_fd))) {
fd = hint_fd;
goto out;
}
prev_fd = service_fd_min_fd() - 1;
list_for_each_entry_reverse(fle, head, used_list) {
fd = fle->fe->fd;
if (prev_fd > fd) {
fd++;
goto out;
}
prev_fd = fd - 1;
}
BUG();
out:
return fd;
}
/* /*
* A file may be shared between several file descriptors. E.g * A file may be shared between several file descriptors. E.g
* when doing a fork() every fd of a forker and respective fds * when doing a fork() every fd of a forker and respective fds
......
...@@ -137,13 +137,7 @@ static inline bool fd_is_used(struct list_head *head, int fd) ...@@ -137,13 +137,7 @@ static inline bool fd_is_used(struct list_head *head, int fd)
return false; return false;
} }
static inline unsigned int find_unused_fd(struct list_head *head, int hint_fd) unsigned int find_unused_fd(struct list_head *head, int hint_fd);
{
if ((hint_fd >= 0) && (!fd_is_used(head, hint_fd)))
return hint_fd;
/* Return last used fd +1 */
return list_entry(head->prev, typeof(struct fdinfo_list_entry), used_list)->fe->fd + 1;
}
struct file_desc { struct file_desc {
u32 id; /* File id, unique */ u32 id; /* File id, unique */
......
...@@ -31,5 +31,6 @@ extern int install_service_fd(enum sfd_type type, int fd); ...@@ -31,5 +31,6 @@ extern int install_service_fd(enum sfd_type type, int fd);
extern int close_service_fd(enum sfd_type type); extern int close_service_fd(enum sfd_type type);
extern bool is_service_fd(int fd, enum sfd_type type); extern bool is_service_fd(int fd, enum sfd_type type);
extern bool is_any_service_fd(int fd); extern bool is_any_service_fd(int fd);
extern int service_fd_min_fd(void);
#endif /* __CR_SERVICE_FD_H__ */ #endif /* __CR_SERVICE_FD_H__ */
...@@ -409,6 +409,11 @@ static int __get_service_fd(enum sfd_type type, int service_fd_id) ...@@ -409,6 +409,11 @@ static int __get_service_fd(enum sfd_type type, int service_fd_id)
return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id; return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id;
} }
int service_fd_min_fd(void)
{
return service_fd_rlim_cur - (SERVICE_FD_MAX - 1) - SERVICE_FD_MAX * service_fd_id;
}
static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX); static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX);
int reserve_service_fd(enum sfd_type type) int reserve_service_fd(enum sfd_type type)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment