cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

proc.c (9589B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* /proc/net/ support for AF_RXRPC
      3 *
      4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
      5 * Written by David Howells (dhowells@redhat.com)
      6 */
      7
      8#include <linux/module.h>
      9#include <net/sock.h>
     10#include <net/af_rxrpc.h>
     11#include "ar-internal.h"
     12
     13static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = {
     14	[RXRPC_CONN_UNUSED]			= "Unused  ",
     15	[RXRPC_CONN_CLIENT]			= "Client  ",
     16	[RXRPC_CONN_SERVICE_PREALLOC]		= "SvPrealc",
     17	[RXRPC_CONN_SERVICE_UNSECURED]		= "SvUnsec ",
     18	[RXRPC_CONN_SERVICE_CHALLENGING]	= "SvChall ",
     19	[RXRPC_CONN_SERVICE]			= "SvSecure",
     20	[RXRPC_CONN_REMOTELY_ABORTED]		= "RmtAbort",
     21	[RXRPC_CONN_LOCALLY_ABORTED]		= "LocAbort",
     22};
     23
     24/*
     25 * generate a list of extant and dead calls in /proc/net/rxrpc_calls
     26 */
     27static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos)
     28	__acquires(rcu)
     29{
     30	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
     31
     32	rcu_read_lock();
     33	return seq_list_start_head_rcu(&rxnet->calls, *_pos);
     34}
     35
     36static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
     37{
     38	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
     39
     40	return seq_list_next_rcu(v, &rxnet->calls, pos);
     41}
     42
     43static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
     44	__releases(rcu)
     45{
     46	rcu_read_unlock();
     47}
     48
     49static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
     50{
     51	struct rxrpc_local *local;
     52	struct rxrpc_sock *rx;
     53	struct rxrpc_peer *peer;
     54	struct rxrpc_call *call;
     55	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
     56	unsigned long timeout = 0;
     57	rxrpc_seq_t tx_hard_ack, rx_hard_ack;
     58	char lbuff[50], rbuff[50];
     59
     60	if (v == &rxnet->calls) {
     61		seq_puts(seq,
     62			 "Proto Local                                          "
     63			 " Remote                                         "
     64			 " SvID ConnID   CallID   End Use State    Abort   "
     65			 " DebugId  TxSeq    TW RxSeq    RW RxSerial RxTimo\n");
     66		return 0;
     67	}
     68
     69	call = list_entry(v, struct rxrpc_call, link);
     70
     71	rx = rcu_dereference(call->socket);
     72	if (rx) {
     73		local = READ_ONCE(rx->local);
     74		if (local)
     75			sprintf(lbuff, "%pISpc", &local->srx.transport);
     76		else
     77			strcpy(lbuff, "no_local");
     78	} else {
     79		strcpy(lbuff, "no_socket");
     80	}
     81
     82	peer = call->peer;
     83	if (peer)
     84		sprintf(rbuff, "%pISpc", &peer->srx.transport);
     85	else
     86		strcpy(rbuff, "no_connection");
     87
     88	if (call->state != RXRPC_CALL_SERVER_PREALLOC) {
     89		timeout = READ_ONCE(call->expect_rx_by);
     90		timeout -= jiffies;
     91	}
     92
     93	tx_hard_ack = READ_ONCE(call->tx_hard_ack);
     94	rx_hard_ack = READ_ONCE(call->rx_hard_ack);
     95	seq_printf(seq,
     96		   "UDP   %-47.47s %-47.47s %4x %08x %08x %s %3u"
     97		   " %-8.8s %08x %08x %08x %02x %08x %02x %08x %06lx\n",
     98		   lbuff,
     99		   rbuff,
    100		   call->service_id,
    101		   call->cid,
    102		   call->call_id,
    103		   rxrpc_is_service_call(call) ? "Svc" : "Clt",
    104		   refcount_read(&call->ref),
    105		   rxrpc_call_states[call->state],
    106		   call->abort_code,
    107		   call->debug_id,
    108		   tx_hard_ack, READ_ONCE(call->tx_top) - tx_hard_ack,
    109		   rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack,
    110		   call->rx_serial,
    111		   timeout);
    112
    113	return 0;
    114}
    115
    116const struct seq_operations rxrpc_call_seq_ops = {
    117	.start  = rxrpc_call_seq_start,
    118	.next   = rxrpc_call_seq_next,
    119	.stop   = rxrpc_call_seq_stop,
    120	.show   = rxrpc_call_seq_show,
    121};
    122
    123/*
    124 * generate a list of extant virtual connections in /proc/net/rxrpc_conns
    125 */
    126static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
    127	__acquires(rxnet->conn_lock)
    128{
    129	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
    130
    131	read_lock(&rxnet->conn_lock);
    132	return seq_list_start_head(&rxnet->conn_proc_list, *_pos);
    133}
    134
    135static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
    136				       loff_t *pos)
    137{
    138	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
    139
    140	return seq_list_next(v, &rxnet->conn_proc_list, pos);
    141}
    142
    143static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
    144	__releases(rxnet->conn_lock)
    145{
    146	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
    147
    148	read_unlock(&rxnet->conn_lock);
    149}
    150
    151static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
    152{
    153	struct rxrpc_connection *conn;
    154	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
    155	char lbuff[50], rbuff[50];
    156
    157	if (v == &rxnet->conn_proc_list) {
    158		seq_puts(seq,
    159			 "Proto Local                                          "
    160			 " Remote                                         "
    161			 " SvID ConnID   End Use State    Key     "
    162			 " Serial   ISerial  CallId0  CallId1  CallId2  CallId3\n"
    163			 );
    164		return 0;
    165	}
    166
    167	conn = list_entry(v, struct rxrpc_connection, proc_link);
    168	if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) {
    169		strcpy(lbuff, "no_local");
    170		strcpy(rbuff, "no_connection");
    171		goto print;
    172	}
    173
    174	sprintf(lbuff, "%pISpc", &conn->params.local->srx.transport);
    175
    176	sprintf(rbuff, "%pISpc", &conn->params.peer->srx.transport);
    177print:
    178	seq_printf(seq,
    179		   "UDP   %-47.47s %-47.47s %4x %08x %s %3u"
    180		   " %s %08x %08x %08x %08x %08x %08x %08x\n",
    181		   lbuff,
    182		   rbuff,
    183		   conn->service_id,
    184		   conn->proto.cid,
    185		   rxrpc_conn_is_service(conn) ? "Svc" : "Clt",
    186		   refcount_read(&conn->ref),
    187		   rxrpc_conn_states[conn->state],
    188		   key_serial(conn->params.key),
    189		   atomic_read(&conn->serial),
    190		   conn->hi_serial,
    191		   conn->channels[0].call_id,
    192		   conn->channels[1].call_id,
    193		   conn->channels[2].call_id,
    194		   conn->channels[3].call_id);
    195
    196	return 0;
    197}
    198
    199const struct seq_operations rxrpc_connection_seq_ops = {
    200	.start  = rxrpc_connection_seq_start,
    201	.next   = rxrpc_connection_seq_next,
    202	.stop   = rxrpc_connection_seq_stop,
    203	.show   = rxrpc_connection_seq_show,
    204};
    205
    206/*
    207 * generate a list of extant virtual peers in /proc/net/rxrpc/peers
    208 */
    209static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
    210{
    211	struct rxrpc_peer *peer;
    212	time64_t now;
    213	char lbuff[50], rbuff[50];
    214
    215	if (v == SEQ_START_TOKEN) {
    216		seq_puts(seq,
    217			 "Proto Local                                          "
    218			 " Remote                                         "
    219			 " Use  CW   MTU LastUse      RTT      RTO\n"
    220			 );
    221		return 0;
    222	}
    223
    224	peer = list_entry(v, struct rxrpc_peer, hash_link);
    225
    226	sprintf(lbuff, "%pISpc", &peer->local->srx.transport);
    227
    228	sprintf(rbuff, "%pISpc", &peer->srx.transport);
    229
    230	now = ktime_get_seconds();
    231	seq_printf(seq,
    232		   "UDP   %-47.47s %-47.47s %3u"
    233		   " %3u %5u %6llus %8u %8u\n",
    234		   lbuff,
    235		   rbuff,
    236		   refcount_read(&peer->ref),
    237		   peer->cong_cwnd,
    238		   peer->mtu,
    239		   now - peer->last_tx_at,
    240		   peer->srtt_us >> 3,
    241		   jiffies_to_usecs(peer->rto_j));
    242
    243	return 0;
    244}
    245
    246static void *rxrpc_peer_seq_start(struct seq_file *seq, loff_t *_pos)
    247	__acquires(rcu)
    248{
    249	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
    250	unsigned int bucket, n;
    251	unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
    252	void *p;
    253
    254	rcu_read_lock();
    255
    256	if (*_pos >= UINT_MAX)
    257		return NULL;
    258
    259	n = *_pos & ((1U << shift) - 1);
    260	bucket = *_pos >> shift;
    261	for (;;) {
    262		if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
    263			*_pos = UINT_MAX;
    264			return NULL;
    265		}
    266		if (n == 0) {
    267			if (bucket == 0)
    268				return SEQ_START_TOKEN;
    269			*_pos += 1;
    270			n++;
    271		}
    272
    273		p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
    274		if (p)
    275			return p;
    276		bucket++;
    277		n = 1;
    278		*_pos = (bucket << shift) | n;
    279	}
    280}
    281
    282static void *rxrpc_peer_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
    283{
    284	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
    285	unsigned int bucket, n;
    286	unsigned int shift = 32 - HASH_BITS(rxnet->peer_hash);
    287	void *p;
    288
    289	if (*_pos >= UINT_MAX)
    290		return NULL;
    291
    292	bucket = *_pos >> shift;
    293
    294	p = seq_hlist_next_rcu(v, &rxnet->peer_hash[bucket], _pos);
    295	if (p)
    296		return p;
    297
    298	for (;;) {
    299		bucket++;
    300		n = 1;
    301		*_pos = (bucket << shift) | n;
    302
    303		if (bucket >= HASH_SIZE(rxnet->peer_hash)) {
    304			*_pos = UINT_MAX;
    305			return NULL;
    306		}
    307		if (n == 0) {
    308			*_pos += 1;
    309			n++;
    310		}
    311
    312		p = seq_hlist_start_rcu(&rxnet->peer_hash[bucket], n - 1);
    313		if (p)
    314			return p;
    315	}
    316}
    317
    318static void rxrpc_peer_seq_stop(struct seq_file *seq, void *v)
    319	__releases(rcu)
    320{
    321	rcu_read_unlock();
    322}
    323
    324
    325const struct seq_operations rxrpc_peer_seq_ops = {
    326	.start  = rxrpc_peer_seq_start,
    327	.next   = rxrpc_peer_seq_next,
    328	.stop   = rxrpc_peer_seq_stop,
    329	.show   = rxrpc_peer_seq_show,
    330};
    331
    332/*
    333 * Generate a list of extant virtual local endpoints in /proc/net/rxrpc/locals
    334 */
    335static int rxrpc_local_seq_show(struct seq_file *seq, void *v)
    336{
    337	struct rxrpc_local *local;
    338	char lbuff[50];
    339
    340	if (v == SEQ_START_TOKEN) {
    341		seq_puts(seq,
    342			 "Proto Local                                          "
    343			 " Use Act\n");
    344		return 0;
    345	}
    346
    347	local = hlist_entry(v, struct rxrpc_local, link);
    348
    349	sprintf(lbuff, "%pISpc", &local->srx.transport);
    350
    351	seq_printf(seq,
    352		   "UDP   %-47.47s %3u %3u\n",
    353		   lbuff,
    354		   refcount_read(&local->ref),
    355		   atomic_read(&local->active_users));
    356
    357	return 0;
    358}
    359
    360static void *rxrpc_local_seq_start(struct seq_file *seq, loff_t *_pos)
    361	__acquires(rcu)
    362{
    363	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
    364	unsigned int n;
    365
    366	rcu_read_lock();
    367
    368	if (*_pos >= UINT_MAX)
    369		return NULL;
    370
    371	n = *_pos;
    372	if (n == 0)
    373		return SEQ_START_TOKEN;
    374
    375	return seq_hlist_start_rcu(&rxnet->local_endpoints, n - 1);
    376}
    377
    378static void *rxrpc_local_seq_next(struct seq_file *seq, void *v, loff_t *_pos)
    379{
    380	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
    381
    382	if (*_pos >= UINT_MAX)
    383		return NULL;
    384
    385	return seq_hlist_next_rcu(v, &rxnet->local_endpoints, _pos);
    386}
    387
    388static void rxrpc_local_seq_stop(struct seq_file *seq, void *v)
    389	__releases(rcu)
    390{
    391	rcu_read_unlock();
    392}
    393
    394const struct seq_operations rxrpc_local_seq_ops = {
    395	.start  = rxrpc_local_seq_start,
    396	.next   = rxrpc_local_seq_next,
    397	.stop   = rxrpc_local_seq_stop,
    398	.show   = rxrpc_local_seq_show,
    399};