mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 05:31:15 +00:00
tty: resolve tty contention between kernel and user space
The commit 12e84c71b7
("tty: export tty_open_by_driver") exports
tty_open_by_device to allow tty to be opened from inside kernel which
works fine except that it doesn't handle contention with user space or
another kernel-space open of the same tty. For example, opening a tty
from user space while it is kernel opened results in failure and a
kernel log message about mismatch between tty->count and tty's file
open count.
This patch makes kernel access to tty exclusive, so that if a user
process or kernel opens a kernel opened tty, it gets -EBUSY. It does
this by adding TTY_KOPENED flag to tty->flags. When this flag is set,
tty_open_by_driver returns -EBUSY. Instead of overloading
tty_open_by_driver for both kernel and user space, this
patch creates a separate function tty_kopen which closely follows
tty_open_by_driver. tty_kclose closes the tty opened by tty_kopen.
To address the mismatch between tty->count and #fd's, this patch adds
#kopen's to the count before comparing it with tty->count. That way
check_tty_count reflects correct usage count.
Returning -EBUSY on tty open is a change in the interface. I have
tested this with minicom, picocom and commands like "echo foo >
/dev/ttyS0". They all correctly report "Device or resource busy" when
the tty is already kernel opened.
Signed-off-by: Okash Khawaja <okash.khawaja@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8439a69e72
commit
a09ac3974d
2 changed files with 116 additions and 5 deletions
|
@ -261,6 +261,8 @@ struct tty_port {
|
|||
*/
|
||||
#define TTY_PORT_CTS_FLOW 3 /* h/w flow control enabled */
|
||||
#define TTY_PORT_CHECK_CD 4 /* carrier detect enabled */
|
||||
#define TTY_PORT_KOPENED 5 /* device exclusively opened by
|
||||
kernel */
|
||||
|
||||
/*
|
||||
* Where all of the state associated with a tty is kept while the tty
|
||||
|
@ -401,6 +403,8 @@ extern int __init tty_init(void);
|
|||
extern const char *tty_name(const struct tty_struct *tty);
|
||||
extern struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode,
|
||||
struct file *filp);
|
||||
extern struct tty_struct *tty_kopen(dev_t device);
|
||||
extern void tty_kclose(struct tty_struct *tty);
|
||||
extern int tty_dev_name_to_number(const char *name, dev_t *number);
|
||||
#else
|
||||
static inline void tty_kref_put(struct tty_struct *tty)
|
||||
|
@ -425,6 +429,10 @@ static inline const char *tty_name(const struct tty_struct *tty)
|
|||
static inline struct tty_struct *tty_open_by_driver(dev_t device,
|
||||
struct inode *inode, struct file *filp)
|
||||
{ return NULL; }
|
||||
static inline struct tty_struct *tty_kopen(dev_t device)
|
||||
{ return ERR_PTR(-ENODEV); }
|
||||
static inline void tty_kclose(struct tty_struct *tty)
|
||||
{ }
|
||||
static inline int tty_dev_name_to_number(const char *name, dev_t *number)
|
||||
{ return -ENOTSUPP; }
|
||||
#endif
|
||||
|
@ -652,6 +660,19 @@ static inline void tty_port_set_initialized(struct tty_port *port, bool val)
|
|||
clear_bit(TTY_PORT_INITIALIZED, &port->iflags);
|
||||
}
|
||||
|
||||
static inline bool tty_port_kopened(struct tty_port *port)
|
||||
{
|
||||
return test_bit(TTY_PORT_KOPENED, &port->iflags);
|
||||
}
|
||||
|
||||
static inline void tty_port_set_kopened(struct tty_port *port, bool val)
|
||||
{
|
||||
if (val)
|
||||
set_bit(TTY_PORT_KOPENED, &port->iflags);
|
||||
else
|
||||
clear_bit(TTY_PORT_KOPENED, &port->iflags);
|
||||
}
|
||||
|
||||
extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
|
||||
extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
|
||||
extern int tty_port_carrier_raised(struct tty_port *port);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue