From: Marco Elver <elver@google.com>
To: elver@google.com
Cc: "David S. Miller" <davem@davemloft.net>,
Luc Van Oostenryck <luc.vanoostenryck@gmail.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
Alexander Potapenko <glider@google.com>,
Arnd Bergmann <arnd@arndb.de>,
Bart Van Assche <bvanassche@acm.org>,
Bill Wendling <morbo@google.com>,
Boqun Feng <boqun.feng@gmail.com>,
Dmitry Vyukov <dvyukov@google.com>,
Eric Dumazet <edumazet@google.com>,
Frederic Weisbecker <frederic@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Herbert Xu <herbert@gondor.apana.org.au>,
Ingo Molnar <mingo@kernel.org>, Jann Horn <jannh@google.com>,
Jiri Slaby <jirislaby@kernel.org>,
Joel Fernandes <joel@joelfernandes.org>,
Jonathan Corbet <corbet@lwn.net>,
Josh Triplett <josh@joshtriplett.org>,
Justin Stitt <justinstitt@google.com>,
Kees Cook <kees@kernel.org>,
Kentaro Takeda <takedakn@nttdata.co.jp>,
Mark Rutland <mark.rutland@arm.com>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Miguel Ojeda <ojeda@kernel.org>,
Nathan Chancellor <nathan@kernel.org>,
Neeraj Upadhyay <neeraj.upadhyay@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Steven Rostedt <rostedt@goodmis.org>,
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>,
Thomas Gleixner <tglx@linutronix.de>,
Uladzislau Rezki <urezki@gmail.com>,
Waiman Long <longman@redhat.com>, Will Deacon <will@kernel.org>,
kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org,
llvm@lists.linux.dev, rcu@vger.kernel.org,
linux-crypto@vger.kernel.org, linux-serial@vger.kernel.org
Subject: [PATCH v2 31/34] drivers/tty: Enable capability analysis for core files
Date: Tue, 4 Mar 2025 10:21:30 +0100 [thread overview]
Message-ID: <20250304092417.2873893-32-elver@google.com> (raw)
In-Reply-To: <20250304092417.2873893-1-elver@google.com>
Enable capability analysis for drivers/tty/*.
This demonstrates a larger conversion to use Clang's capability
analysis. The benefit is additional static checking of locking rules,
along with better documentation.
Signed-off-by: Marco Elver <elver@google.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jirislaby@kernel.org>
---
v2:
* New patch.
---
drivers/tty/Makefile | 3 +++
drivers/tty/n_tty.c | 16 ++++++++++++++++
drivers/tty/pty.c | 1 +
drivers/tty/sysrq.c | 1 +
drivers/tty/tty.h | 8 ++++----
drivers/tty/tty_buffer.c | 8 +++-----
drivers/tty/tty_io.c | 12 +++++++++---
drivers/tty/tty_ioctl.c | 2 +-
drivers/tty/tty_ldisc.c | 35 ++++++++++++++++++++++++++++++++---
drivers/tty/tty_ldsem.c | 2 ++
drivers/tty/tty_mutex.c | 4 ++++
drivers/tty/tty_port.c | 2 ++
include/linux/tty.h | 14 +++++++-------
include/linux/tty_flip.h | 4 ++--
include/linux/tty_ldisc.h | 19 ++++++++++---------
15 files changed, 97 insertions(+), 34 deletions(-)
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 07aca5184a55..35e1a62cbe16 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
+
+CAPABILITY_ANALYSIS := y
+
obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \
tty_buffer.o tty_port.o tty_mutex.o \
tty_ldsem.o tty_baudrate.o tty_jobctrl.o \
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 5e9ca4376d68..45925fc5a8fd 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1088,6 +1088,7 @@ static void __isig(int sig, struct tty_struct *tty)
* Locking: %ctrl.lock
*/
static void isig(int sig, struct tty_struct *tty)
+ __must_hold_shared(&tty->termios_rwsem)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1135,6 +1136,7 @@ static void isig(int sig, struct tty_struct *tty)
* Note: may get exclusive %termios_rwsem if flushing input buffer
*/
static void n_tty_receive_break(struct tty_struct *tty)
+ __must_hold_shared(&tty->termios_rwsem)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1204,6 +1206,7 @@ static void n_tty_receive_parity_error(const struct tty_struct *tty,
static void
n_tty_receive_signal_char(struct tty_struct *tty, int signal, u8 c)
+ __must_hold_shared(&tty->termios_rwsem)
{
isig(signal, tty);
if (I_IXON(tty))
@@ -1353,6 +1356,7 @@ static bool n_tty_receive_char_canon(struct tty_struct *tty, u8 c)
static void n_tty_receive_char_special(struct tty_struct *tty, u8 c,
bool lookahead_done)
+ __must_hold_shared(&tty->termios_rwsem)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1463,6 +1467,7 @@ static void n_tty_receive_char_closing(struct tty_struct *tty, u8 c,
static void
n_tty_receive_char_flagged(struct tty_struct *tty, u8 c, u8 flag)
+ __must_hold_shared(&tty->termios_rwsem)
{
switch (flag) {
case TTY_BREAK:
@@ -1483,6 +1488,7 @@ n_tty_receive_char_flagged(struct tty_struct *tty, u8 c, u8 flag)
static void
n_tty_receive_char_lnext(struct tty_struct *tty, u8 c, u8 flag)
+ __must_hold_shared(&tty->termios_rwsem)
{
struct n_tty_data *ldata = tty->disc_data;
@@ -1540,6 +1546,7 @@ n_tty_receive_buf_real_raw(const struct tty_struct *tty, const u8 *cp,
static void
n_tty_receive_buf_raw(struct tty_struct *tty, const u8 *cp, const u8 *fp,
size_t count)
+ __must_hold_shared(&tty->termios_rwsem)
{
struct n_tty_data *ldata = tty->disc_data;
u8 flag = TTY_NORMAL;
@@ -1571,6 +1578,7 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const u8 *cp, const u8 *fp,
static void n_tty_receive_buf_standard(struct tty_struct *tty, const u8 *cp,
const u8 *fp, size_t count,
bool lookahead_done)
+ __must_hold_shared(&tty->termios_rwsem)
{
struct n_tty_data *ldata = tty->disc_data;
u8 flag = TTY_NORMAL;
@@ -1609,6 +1617,7 @@ static void n_tty_receive_buf_standard(struct tty_struct *tty, const u8 *cp,
static void __receive_buf(struct tty_struct *tty, const u8 *cp, const u8 *fp,
size_t count)
+ __must_hold_shared(&tty->termios_rwsem)
{
struct n_tty_data *ldata = tty->disc_data;
bool preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty));
@@ -2188,6 +2197,10 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, u8 *kbuf,
return kb - kbuf;
}
+ /* Adopted locks from prior call. */
+ __acquire(&ldata->atomic_read_lock);
+ __acquire_shared(&tty->termios_rwsem);
+
/* No more data - release locks and stop retries */
n_tty_kick_worker(tty);
n_tty_check_unthrottle(tty);
@@ -2305,6 +2318,9 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, u8 *kbuf,
more_to_be_read:
remove_wait_queue(&tty->read_wait, &wait);
*cookie = cookie;
+ /* Hand-off locks to retry with cookie set. */
+ __release_shared(&tty->termios_rwsem);
+ __release(&ldata->atomic_read_lock);
return kb - kbuf;
}
}
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 8bb1a01fef2a..8d4eb0f4c84c 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -824,6 +824,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
tty = tty_init_dev(ptm_driver, index);
/* The tty returned here is locked so we can safely
drop the mutex */
+ lockdep_assert_held(&tty->legacy_mutex);
mutex_unlock(&tty_mutex);
retval = PTR_ERR(tty);
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index f85ce02e4725..82dfa964c965 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -149,6 +149,7 @@ static const struct sysrq_key_op sysrq_unraw_op = {
static void sysrq_handle_crash(u8 key)
{
/* release the RCU read lock before crashing */
+ lockdep_assert_in_rcu_read_lock();
rcu_read_unlock();
panic("sysrq triggered crash\n");
diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
index 93cf5ef1e857..1a3c2f663b28 100644
--- a/drivers/tty/tty.h
+++ b/drivers/tty/tty.h
@@ -60,15 +60,15 @@ static inline void tty_set_flow_change(struct tty_struct *tty,
smp_mb();
}
-int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
-void tty_ldisc_unlock(struct tty_struct *tty);
+int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) __cond_acquires(0, &tty->ldisc_sem);
+void tty_ldisc_unlock(struct tty_struct *tty) __releases(&tty->ldisc_sem);
int __tty_check_change(struct tty_struct *tty, int sig);
int tty_check_change(struct tty_struct *tty);
void __stop_tty(struct tty_struct *tty);
void __start_tty(struct tty_struct *tty);
-void tty_write_unlock(struct tty_struct *tty);
-int tty_write_lock(struct tty_struct *tty, bool ndelay);
+void tty_write_unlock(struct tty_struct *tty) __releases(&tty->atomic_write_lock);
+int tty_write_lock(struct tty_struct *tty, bool ndelay) __cond_acquires(0, &tty->atomic_write_lock);
void tty_vhangup_session(struct tty_struct *tty);
void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty);
int tty_signal_session_leader(struct tty_struct *tty, int exit_session);
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 79f0ff94ce00..dcc56537290f 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -52,10 +52,8 @@
*/
void tty_buffer_lock_exclusive(struct tty_port *port)
{
- struct tty_bufhead *buf = &port->buf;
-
- atomic_inc(&buf->priority);
- mutex_lock(&buf->lock);
+ atomic_inc(&port->buf.priority);
+ mutex_lock(&port->buf.lock);
}
EXPORT_SYMBOL_GPL(tty_buffer_lock_exclusive);
@@ -73,7 +71,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port)
bool restart = buf->head->commit != buf->head->read;
atomic_dec(&buf->priority);
- mutex_unlock(&buf->lock);
+ mutex_unlock(&port->buf.lock);
if (restart)
queue_work(system_unbound_wq, &buf->work);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 449dbd216460..1eb3794fde4b 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -167,6 +167,7 @@ static void release_tty(struct tty_struct *tty, int idx);
* Locking: none. Must be called after tty is definitely unused
*/
static void free_tty_struct(struct tty_struct *tty)
+ __capability_unsafe(/* destructor */)
{
tty_ldisc_deinit(tty);
put_device(tty->dev);
@@ -965,7 +966,7 @@ static ssize_t iterate_tty_write(struct tty_ldisc *ld, struct tty_struct *tty,
ssize_t ret, written = 0;
ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
- if (ret < 0)
+ if (ret)
return ret;
/*
@@ -1154,7 +1155,7 @@ int tty_send_xchar(struct tty_struct *tty, u8 ch)
return 0;
}
- if (tty_write_lock(tty, false) < 0)
+ if (tty_write_lock(tty, false))
return -ERESTARTSYS;
down_read(&tty->termios_rwsem);
@@ -1391,6 +1392,7 @@ static int tty_reopen(struct tty_struct *tty)
* Return: new tty structure
*/
struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
+ __capability_unsafe(/* returns with locked tty */)
{
struct tty_struct *tty;
int retval;
@@ -1874,6 +1876,7 @@ int tty_release(struct inode *inode, struct file *filp)
* will not work then. It expects inodes to be from devpts FS.
*/
static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
+ __capability_unsafe(/* returns with locked tty */)
{
struct tty_struct *tty;
int retval;
@@ -2037,6 +2040,7 @@ EXPORT_SYMBOL_GPL(tty_kopen_shared);
*/
static struct tty_struct *tty_open_by_driver(dev_t device,
struct file *filp)
+ __capability_unsafe(/* returns with locked tty */)
{
struct tty_struct *tty;
struct tty_driver *driver = NULL;
@@ -2137,6 +2141,8 @@ static int tty_open(struct inode *inode, struct file *filp)
goto retry_open;
}
+ lockdep_assert_held(&tty->legacy_mutex);
+
tty_add_file(tty, filp);
check_tty_count(tty, __func__);
@@ -2486,7 +2492,7 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
return tty->ops->break_ctl(tty, duration);
/* Do the work ourselves */
- if (tty_write_lock(tty, false) < 0)
+ if (tty_write_lock(tty, false))
return -EINTR;
retval = tty->ops->break_ctl(tty, -1);
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 85de90eebc7b..a7ae6cbf3450 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -489,7 +489,7 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
if (retval < 0)
return retval;
- if (tty_write_lock(tty, false) < 0)
+ if (tty_write_lock(tty, false))
goto retry_write_wait;
/* Racing writer? */
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index d80e9d4c974b..e07a5980604e 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -237,6 +237,7 @@ const struct seq_operations tty_ldiscs_seq_ops = {
* to wait for any ldisc lifetime events to finish.
*/
struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
+ __cond_acquires_shared(nonnull, &tty->ldisc_sem)
{
struct tty_ldisc *ld;
@@ -257,6 +258,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
* and timer functions.
*/
struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
+ __cond_acquires_shared(nonnull, &tty->ldisc_sem)
{
struct tty_ldisc *ld = NULL;
@@ -277,26 +279,43 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
* in IRQ context.
*/
void tty_ldisc_deref(struct tty_ldisc *ld)
+ __releases_shared(&ld->tty->ldisc_sem)
{
ldsem_up_read(&ld->tty->ldisc_sem);
}
EXPORT_SYMBOL_GPL(tty_ldisc_deref);
+/*
+ * Note: Capability analysis does not like asymmetric interfaces (above types
+ * for ref and deref are tty_struct and tty_ldisc respectively -- which are
+ * dependent, but the compiler cannot figure that out); in this case, work
+ * around that with this helper which takes an unused @tty argument but tells
+ * the analysis which lock is released.
+ */
+static inline void __tty_ldisc_deref(struct tty_struct *tty, struct tty_ldisc *ld)
+ __releases_shared(&tty->ldisc_sem)
+ __capability_unsafe(/* matches released with tty_ldisc_ref() */)
+{
+ tty_ldisc_deref(ld);
+}
static inline int
__tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)
+ __cond_acquires(true, &tty->ldisc_sem)
{
return ldsem_down_write(&tty->ldisc_sem, timeout);
}
static inline int
__tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout)
+ __cond_acquires(true, &tty->ldisc_sem)
{
return ldsem_down_write_nested(&tty->ldisc_sem,
LDISC_SEM_OTHER, timeout);
}
static inline void __tty_ldisc_unlock(struct tty_struct *tty)
+ __releases(&tty->ldisc_sem)
{
ldsem_up_write(&tty->ldisc_sem);
}
@@ -328,6 +347,8 @@ void tty_ldisc_unlock(struct tty_struct *tty)
static int
tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2,
unsigned long timeout)
+ __cond_acquires(0, &tty->ldisc_sem)
+ __cond_acquires(0, &tty2->ldisc_sem)
{
int ret;
@@ -362,16 +383,23 @@ tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2,
}
static void tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2)
+ __acquires(&tty->ldisc_sem)
+ __acquires(&tty2->ldisc_sem)
+ __capability_unsafe(/* MAX_SCHEDULE_TIMEOUT ensures acquisition */)
{
tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT);
}
static void tty_ldisc_unlock_pair(struct tty_struct *tty,
struct tty_struct *tty2)
+ __releases(&tty->ldisc_sem)
+ __releases(&tty2->ldisc_sem)
{
__tty_ldisc_unlock(tty);
if (tty2)
__tty_ldisc_unlock(tty2);
+ else
+ __release(&tty2->ldisc_sem);
}
/**
@@ -387,7 +415,7 @@ void tty_ldisc_flush(struct tty_struct *tty)
tty_buffer_flush(tty, ld);
if (ld)
- tty_ldisc_deref(ld);
+ __tty_ldisc_deref(tty, ld);
}
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
@@ -694,7 +722,7 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit)
tty_ldisc_debug(tty, "%p: hangup\n", tty->ldisc);
ld = tty_ldisc_ref(tty);
- if (ld != NULL) {
+ if (ld) {
if (ld->ops->flush_buffer)
ld->ops->flush_buffer(tty);
tty_driver_flush_buffer(tty);
@@ -703,7 +731,7 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit)
ld->ops->write_wakeup(tty);
if (ld->ops->hangup)
ld->ops->hangup(tty);
- tty_ldisc_deref(ld);
+ __tty_ldisc_deref(tty, ld);
}
wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT);
@@ -716,6 +744,7 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit)
* Avoid racing set_ldisc or tty_ldisc_release
*/
tty_ldisc_lock(tty, MAX_SCHEDULE_TIMEOUT);
+ lockdep_assert_held_write(&tty->ldisc_sem);
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
tty_reset_termios(tty);
diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c
index 3be428c16260..26d924bb5a46 100644
--- a/drivers/tty/tty_ldsem.c
+++ b/drivers/tty/tty_ldsem.c
@@ -390,6 +390,7 @@ void ldsem_up_read(struct ld_semaphore *sem)
{
long count;
+ __release_shared(sem);
rwsem_release(&sem->dep_map, _RET_IP_);
count = atomic_long_add_return(-LDSEM_READ_BIAS, &sem->count);
@@ -404,6 +405,7 @@ void ldsem_up_write(struct ld_semaphore *sem)
{
long count;
+ __release(sem);
rwsem_release(&sem->dep_map, _RET_IP_);
count = atomic_long_add_return(-LDSEM_WRITE_BIAS, &sem->count);
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 784e46a0a3b1..e5576fd6f5a4 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -41,12 +41,16 @@ void tty_lock_slave(struct tty_struct *tty)
{
if (tty && tty != tty->link)
tty_lock(tty);
+ else
+ __acquire(&tty->legacy_mutex);
}
void tty_unlock_slave(struct tty_struct *tty)
{
if (tty && tty != tty->link)
tty_unlock(tty);
+ else
+ __release(&tty->legacy_mutex);
}
void tty_set_lock_subclass(struct tty_struct *tty)
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 14cca33d2269..bcb65a26a6bf 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -509,6 +509,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts);
*/
int tty_port_block_til_ready(struct tty_port *port,
struct tty_struct *tty, struct file *filp)
+ __must_hold(&tty->legacy_mutex)
{
int do_clocal = 0, retval;
unsigned long flags;
@@ -764,6 +765,7 @@ EXPORT_SYMBOL_GPL(tty_port_install);
*/
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
+ __must_hold(&tty->legacy_mutex)
{
spin_lock_irq(&port->lock);
++port->count;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 2372f9357240..ee1ba62fc398 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -234,8 +234,8 @@ struct tty_struct {
void *disc_data;
void *driver_data;
spinlock_t files_lock;
- int write_cnt;
- u8 *write_buf;
+ int write_cnt __guarded_by(&atomic_write_lock);
+ u8 *write_buf __guarded_by(&atomic_write_lock);
struct list_head tty_files;
@@ -500,11 +500,11 @@ long vt_compat_ioctl(struct tty_struct *tty, unsigned int cmd,
/* tty_mutex.c */
/* functions for preparation of BKL removal */
-void tty_lock(struct tty_struct *tty);
-int tty_lock_interruptible(struct tty_struct *tty);
-void tty_unlock(struct tty_struct *tty);
-void tty_lock_slave(struct tty_struct *tty);
-void tty_unlock_slave(struct tty_struct *tty);
+void tty_lock(struct tty_struct *tty) __acquires(&tty->legacy_mutex);
+int tty_lock_interruptible(struct tty_struct *tty) __cond_acquires(0, &tty->legacy_mutex);
+void tty_unlock(struct tty_struct *tty) __releases(&tty->legacy_mutex);
+void tty_lock_slave(struct tty_struct *tty) __acquires(&tty->legacy_mutex);
+void tty_unlock_slave(struct tty_struct *tty) __releases(&tty->legacy_mutex);
void tty_set_lock_subclass(struct tty_struct *tty);
#endif
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index af4fce98f64e..2214714059f8 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -86,7 +86,7 @@ static inline size_t tty_insert_flip_string(struct tty_port *port,
size_t tty_ldisc_receive_buf(struct tty_ldisc *ld, const u8 *p, const u8 *f,
size_t count);
-void tty_buffer_lock_exclusive(struct tty_port *port);
-void tty_buffer_unlock_exclusive(struct tty_port *port);
+void tty_buffer_lock_exclusive(struct tty_port *port) __acquires(&port->buf.lock);
+void tty_buffer_unlock_exclusive(struct tty_port *port) __releases(&port->buf.lock);
#endif /* _LINUX_TTY_FLIP_H */
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index af01e89074b2..d834cf115d52 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -14,7 +14,7 @@ struct tty_struct;
/*
* the semaphore definition
*/
-struct ld_semaphore {
+struct_with_capability(ld_semaphore) {
atomic_long_t count;
raw_spinlock_t wait_lock;
unsigned int wait_readers;
@@ -33,21 +33,22 @@ do { \
static struct lock_class_key __key; \
\
__init_ldsem((sem), #sem, &__key); \
+ __assert_cap(sem); \
} while (0)
-int ldsem_down_read(struct ld_semaphore *sem, long timeout);
-int ldsem_down_read_trylock(struct ld_semaphore *sem);
-int ldsem_down_write(struct ld_semaphore *sem, long timeout);
-int ldsem_down_write_trylock(struct ld_semaphore *sem);
-void ldsem_up_read(struct ld_semaphore *sem);
-void ldsem_up_write(struct ld_semaphore *sem);
+int ldsem_down_read(struct ld_semaphore *sem, long timeout) __cond_acquires_shared(true, sem);
+int ldsem_down_read_trylock(struct ld_semaphore *sem) __cond_acquires_shared(true, sem);
+int ldsem_down_write(struct ld_semaphore *sem, long timeout) __cond_acquires(true, sem);
+int ldsem_down_write_trylock(struct ld_semaphore *sem) __cond_acquires(true, sem);
+void ldsem_up_read(struct ld_semaphore *sem) __releases_shared(sem);
+void ldsem_up_write(struct ld_semaphore *sem) __releases(sem);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
int ldsem_down_read_nested(struct ld_semaphore *sem, int subclass,
- long timeout);
+ long timeout) __cond_acquires_shared(true, sem);
int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass,
- long timeout);
+ long timeout) __cond_acquires(true, sem);
#else
# define ldsem_down_read_nested(sem, subclass, timeout) \
ldsem_down_read(sem, timeout)
--
2.48.1.711.g2feabab25a-goog
next prev parent reply other threads:[~2025-03-04 9:26 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-04 9:20 [PATCH v2 00/34] Compiler-Based Capability- and Locking-Analysis Marco Elver
2025-03-04 9:21 ` [PATCH v2 01/34] compiler_types: Move lock checking attributes to compiler-capability-analysis.h Marco Elver
2025-03-04 23:26 ` Bart Van Assche
2025-03-05 8:36 ` Dan Carpenter
2025-03-05 9:13 ` Marco Elver
2025-03-05 9:27 ` Dan Carpenter
2025-03-04 9:21 ` [PATCH v2 02/34] compiler-capability-analysis: Add infrastructure for Clang's capability analysis Marco Elver
2025-03-04 15:29 ` Peter Zijlstra
2025-03-04 16:05 ` Marco Elver
2025-03-04 9:21 ` [PATCH v2 03/34] compiler-capability-analysis: Add test stub Marco Elver
2025-03-04 23:52 ` Bart Van Assche
2025-03-05 0:03 ` Marco Elver
2025-03-04 9:21 ` [PATCH v2 04/34] Documentation: Add documentation for Compiler-Based Capability Analysis Marco Elver
2025-03-04 9:21 ` [PATCH v2 05/34] checkpatch: Warn about capability_unsafe() without comment Marco Elver
2025-03-04 9:21 ` [PATCH v2 06/34] cleanup: Basic compatibility with capability analysis Marco Elver
2025-03-04 12:55 ` Peter Zijlstra
2025-03-04 13:09 ` Marco Elver
2025-03-04 23:57 ` Bart Van Assche
2025-03-04 9:21 ` [PATCH v2 07/34] lockdep: Annotate lockdep assertions for " Marco Elver
2025-03-04 9:21 ` [PATCH v2 08/34] locking/rwlock, spinlock: Support Clang's " Marco Elver
2025-03-04 14:30 ` Peter Zijlstra
2025-03-04 9:21 ` [PATCH v2 09/34] compiler-capability-analysis: Change __cond_acquires to take return value Marco Elver
2025-03-04 9:21 ` [PATCH v2 10/34] locking/mutex: Support Clang's capability analysis Marco Elver
2025-03-04 9:21 ` [PATCH v2 11/34] locking/seqlock: " Marco Elver
2025-03-04 9:21 ` [PATCH v2 12/34] bit_spinlock: Include missing <asm/processor.h> Marco Elver
2025-03-04 9:21 ` [PATCH v2 13/34] bit_spinlock: Support Clang's capability analysis Marco Elver
2025-03-04 9:21 ` [PATCH v2 14/34] rcu: " Marco Elver
2025-03-04 9:21 ` [PATCH v2 15/34] srcu: " Marco Elver
2025-03-04 9:21 ` [PATCH v2 16/34] kref: Add capability-analysis annotations Marco Elver
2025-03-04 9:21 ` [PATCH v2 17/34] locking/rwsem: Support Clang's capability analysis Marco Elver
2025-03-04 9:21 ` [PATCH v2 18/34] locking/local_lock: Include missing headers Marco Elver
2025-03-04 9:21 ` [PATCH v2 19/34] locking/local_lock: Support Clang's capability analysis Marco Elver
2025-03-04 9:21 ` [PATCH v2 20/34] locking/ww_mutex: " Marco Elver
2025-03-04 9:21 ` [PATCH v2 21/34] debugfs: Make debugfs_cancellation a capability struct Marco Elver
2025-03-04 9:21 ` [PATCH v2 22/34] compiler-capability-analysis: Remove Sparse support Marco Elver
2025-03-04 9:21 ` [PATCH v2 23/34] compiler-capability-analysis: Remove __cond_lock() function-like helper Marco Elver
2025-03-04 23:25 ` Bart Van Assche
2025-03-04 9:21 ` [PATCH v2 24/34] compiler-capability-analysis: Introduce header suppressions Marco Elver
2025-03-04 9:21 ` [PATCH v2 25/34] compiler: Let data_race() imply disabled capability analysis Marco Elver
2025-03-04 9:21 ` [PATCH v2 26/34] kfence: Enable " Marco Elver
2025-03-04 9:21 ` [PATCH v2 27/34] kcov: " Marco Elver
2025-03-04 9:21 ` [PATCH v2 28/34] stackdepot: " Marco Elver
2025-03-04 9:21 ` [PATCH v2 29/34] rhashtable: " Marco Elver
2025-03-04 9:21 ` [PATCH v2 30/34] printk: Move locking annotation to printk.c Marco Elver
2025-03-04 9:21 ` Marco Elver [this message]
2025-03-05 9:15 ` [PATCH v2 31/34] drivers/tty: Enable capability analysis for core files Jiri Slaby
2025-03-05 9:26 ` Marco Elver
2025-03-04 9:21 ` [PATCH v2 32/34] security/tomoyo: Enable capability analysis Marco Elver
2025-03-04 9:21 ` [PATCH v2 33/34] crypto: " Marco Elver
2025-03-04 9:21 ` [PATCH v2 34/34] MAINTAINERS: Add entry for Capability Analysis Marco Elver
2025-03-04 23:18 ` Bart Van Assche
2025-03-04 11:21 ` [PATCH v2 00/34] Compiler-Based Capability- and Locking-Analysis Peter Zijlstra
2025-03-04 11:43 ` Marco Elver
2025-03-05 11:20 ` Peter Zijlstra
2025-03-05 15:27 ` Bart Van Assche
2025-03-05 16:16 ` Peter Zijlstra
2025-08-06 13:36 ` Marco Elver
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250304092417.2873893-32-elver@google.com \
--to=elver@google.com \
--cc=arnd@arndb.de \
--cc=boqun.feng@gmail.com \
--cc=bvanassche@acm.org \
--cc=corbet@lwn.net \
--cc=davem@davemloft.net \
--cc=dvyukov@google.com \
--cc=edumazet@google.com \
--cc=frederic@kernel.org \
--cc=glider@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=herbert@gondor.apana.org.au \
--cc=jannh@google.com \
--cc=jirislaby@kernel.org \
--cc=joel@joelfernandes.org \
--cc=josh@joshtriplett.org \
--cc=justinstitt@google.com \
--cc=kasan-dev@googlegroups.com \
--cc=kees@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=longman@redhat.com \
--cc=luc.vanoostenryck@gmail.com \
--cc=mark.rutland@arm.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@kernel.org \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=neeraj.upadhyay@kernel.org \
--cc=ojeda@kernel.org \
--cc=paulmck@kernel.org \
--cc=penguin-kernel@I-love.SAKURA.ne.jp \
--cc=peterz@infradead.org \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=takedakn@nttdata.co.jp \
--cc=tglx@linutronix.de \
--cc=urezki@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox