SYSCALL_DEFINE1(close, unsigned int, fd) { struct file * filp; struct files_struct *files = current->files; struct fdtable *fdt; int retval; spin_lock(&files->file_lock); fdt = files_fdtable(files); if (fd >= fdt->max_fds) { pr_debug("[%s] fd %u exceeds max_fds %u (user: %s %d:%d)\n", __func__, fd, fdt->max_fds, current->comm, current->tgid, current->pid); goto out_unlock; } filp = fdt->fd[fd]; if (!filp) { struct fdt_user* user = &fdt->user[fd]; if (unlikely(user->remover && user->remover != current->pid)) { struct task_struct* task = find_task_by_vpid(user->remover); pr_warn("[%s] fd %u of %s %d:%d is" " already closed by thread %d (%s %d:%d)\n", __func__, fd, current->comm, current->tgid, current->pid, user->remover, task ? task->comm : "<unknown>", task ? task->tgid : -1, task ? task->pid : -1); } goto out_unlock; } #ifdef CONFIG_HTC_FD_MONITOR if (in_fd_list(fd, 0) == 1) { printk("fd error: %s(%d) tries to close fd=%d illegally\n", current->comm, current->pid, fd); force_sig(SIGABRT, current); spin_unlock(&files->file_lock); force_sig(SIGABRT, current); return 0xBADFD; } #endif rcu_assign_pointer(fdt->fd[fd], NULL); fdt->user[fd].remover = current->pid; __clear_close_on_exec(fd, fdt); __put_unused_fd(files, fd); spin_unlock(&files->file_lock); retval = filp_close(filp, files); if (unlikely(retval == -ERESTARTSYS || retval == -ERESTARTNOINTR || retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK)) retval = -EINTR; return retval; out_unlock: spin_unlock(&files->file_lock); return -EBADF; }
SYSCALL_DEFINE1(close, unsigned int, fd) { int retval; #ifdef CONFIG_HTC_FD_MONITOR if (in_fd_list(fd, 0) == 1) { printk("fd error: %s(%d) tries to close fd=%d illegally\n", current->comm, current->pid, fd); force_sig(SIGABRT, current); force_sig(SIGABRT, current); return 0xBADFD; } #endif retval = __close_fd(current->files, fd); if (unlikely(retval == -ERESTARTSYS || retval == -ERESTARTNOINTR || retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK)) retval = -EINTR; return retval; }