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

capi.c (15296B)


      1/*
      2   CMTP implementation for Linux Bluetooth stack (BlueZ).
      3   Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
      4
      5   This program is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU General Public License version 2 as
      7   published by the Free Software Foundation;
      8
      9   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     10   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     11   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
     12   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
     13   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
     14   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17
     18   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     19   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
     20   SOFTWARE IS DISCLAIMED.
     21*/
     22
     23#include <linux/export.h>
     24#include <linux/proc_fs.h>
     25#include <linux/seq_file.h>
     26#include <linux/types.h>
     27#include <linux/errno.h>
     28#include <linux/kernel.h>
     29#include <linux/sched/signal.h>
     30#include <linux/slab.h>
     31#include <linux/poll.h>
     32#include <linux/fcntl.h>
     33#include <linux/skbuff.h>
     34#include <linux/socket.h>
     35#include <linux/ioctl.h>
     36#include <linux/file.h>
     37#include <linux/wait.h>
     38#include <linux/kthread.h>
     39#include <net/sock.h>
     40
     41#include <linux/isdn/capilli.h>
     42#include <linux/isdn/capicmd.h>
     43#include <linux/isdn/capiutil.h>
     44
     45#include "cmtp.h"
     46
     47#define CAPI_INTEROPERABILITY		0x20
     48
     49#define CAPI_INTEROPERABILITY_REQ	CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
     50#define CAPI_INTEROPERABILITY_CONF	CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
     51#define CAPI_INTEROPERABILITY_IND	CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
     52#define CAPI_INTEROPERABILITY_RESP	CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
     53
     54#define CAPI_INTEROPERABILITY_REQ_LEN	(CAPI_MSG_BASELEN + 2)
     55#define CAPI_INTEROPERABILITY_CONF_LEN	(CAPI_MSG_BASELEN + 4)
     56#define CAPI_INTEROPERABILITY_IND_LEN	(CAPI_MSG_BASELEN + 2)
     57#define CAPI_INTEROPERABILITY_RESP_LEN	(CAPI_MSG_BASELEN + 2)
     58
     59#define CAPI_FUNCTION_REGISTER		0
     60#define CAPI_FUNCTION_RELEASE		1
     61#define CAPI_FUNCTION_GET_PROFILE	2
     62#define CAPI_FUNCTION_GET_MANUFACTURER	3
     63#define CAPI_FUNCTION_GET_VERSION	4
     64#define CAPI_FUNCTION_GET_SERIAL_NUMBER	5
     65#define CAPI_FUNCTION_MANUFACTURER	6
     66#define CAPI_FUNCTION_LOOPBACK		7
     67
     68
     69#define CMTP_MSGNUM	1
     70#define CMTP_APPLID	2
     71#define CMTP_MAPPING	3
     72
     73static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
     74{
     75	struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL);
     76
     77	BT_DBG("session %p application %p appl %u", session, app, appl);
     78
     79	if (!app)
     80		return NULL;
     81
     82	app->state = BT_OPEN;
     83	app->appl = appl;
     84
     85	list_add_tail(&app->list, &session->applications);
     86
     87	return app;
     88}
     89
     90static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
     91{
     92	BT_DBG("session %p application %p", session, app);
     93
     94	if (app) {
     95		list_del(&app->list);
     96		kfree(app);
     97	}
     98}
     99
    100static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
    101{
    102	struct cmtp_application *app;
    103
    104	list_for_each_entry(app, &session->applications, list) {
    105		switch (pattern) {
    106		case CMTP_MSGNUM:
    107			if (app->msgnum == value)
    108				return app;
    109			break;
    110		case CMTP_APPLID:
    111			if (app->appl == value)
    112				return app;
    113			break;
    114		case CMTP_MAPPING:
    115			if (app->mapping == value)
    116				return app;
    117			break;
    118		}
    119	}
    120
    121	return NULL;
    122}
    123
    124static int cmtp_msgnum_get(struct cmtp_session *session)
    125{
    126	session->msgnum++;
    127
    128	if ((session->msgnum & 0xff) > 200)
    129		session->msgnum = CMTP_INITIAL_MSGNUM + 1;
    130
    131	return session->msgnum;
    132}
    133
    134static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
    135{
    136	struct cmtp_scb *scb = (void *) skb->cb;
    137
    138	BT_DBG("session %p skb %p len %u", session, skb, skb->len);
    139
    140	scb->id = -1;
    141	scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
    142
    143	skb_queue_tail(&session->transmit, skb);
    144
    145	wake_up_interruptible(sk_sleep(session->sock->sk));
    146}
    147
    148static void cmtp_send_interopmsg(struct cmtp_session *session,
    149					__u8 subcmd, __u16 appl, __u16 msgnum,
    150					__u16 function, unsigned char *buf, int len)
    151{
    152	struct sk_buff *skb;
    153	unsigned char *s;
    154
    155	BT_DBG("session %p subcmd 0x%02x appl %u msgnum %u", session, subcmd, appl, msgnum);
    156
    157	skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC);
    158	if (!skb) {
    159		BT_ERR("Can't allocate memory for interoperability packet");
    160		return;
    161	}
    162
    163	s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
    164
    165	capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
    166	capimsg_setu16(s, 2, appl);
    167	capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
    168	capimsg_setu8 (s, 5, subcmd);
    169	capimsg_setu16(s, 6, msgnum);
    170
    171	/* Interoperability selector (Bluetooth Device Management) */
    172	capimsg_setu16(s, 8, 0x0001);
    173
    174	capimsg_setu8 (s, 10, 3 + len);
    175	capimsg_setu16(s, 11, function);
    176	capimsg_setu8 (s, 13, len);
    177
    178	if (len > 0)
    179		memcpy(s + 14, buf, len);
    180
    181	cmtp_send_capimsg(session, skb);
    182}
    183
    184static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
    185{
    186	struct capi_ctr *ctrl = &session->ctrl;
    187	struct cmtp_application *application;
    188	__u16 appl, msgnum, func, info;
    189	__u32 controller;
    190
    191	BT_DBG("session %p skb %p len %u", session, skb, skb->len);
    192
    193	switch (CAPIMSG_SUBCOMMAND(skb->data)) {
    194	case CAPI_CONF:
    195		if (skb->len < CAPI_MSG_BASELEN + 10)
    196			break;
    197
    198		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
    199		info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
    200
    201		switch (func) {
    202		case CAPI_FUNCTION_REGISTER:
    203			msgnum = CAPIMSG_MSGID(skb->data);
    204
    205			application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
    206			if (application) {
    207				application->state = BT_CONNECTED;
    208				application->msgnum = 0;
    209				application->mapping = CAPIMSG_APPID(skb->data);
    210				wake_up_interruptible(&session->wait);
    211			}
    212
    213			break;
    214
    215		case CAPI_FUNCTION_RELEASE:
    216			appl = CAPIMSG_APPID(skb->data);
    217
    218			application = cmtp_application_get(session, CMTP_MAPPING, appl);
    219			if (application) {
    220				application->state = BT_CLOSED;
    221				application->msgnum = 0;
    222				wake_up_interruptible(&session->wait);
    223			}
    224
    225			break;
    226
    227		case CAPI_FUNCTION_GET_PROFILE:
    228			if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
    229				break;
    230
    231			controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
    232			msgnum = CAPIMSG_MSGID(skb->data);
    233
    234			if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
    235				session->ncontroller = controller;
    236				wake_up_interruptible(&session->wait);
    237				break;
    238			}
    239
    240			if (!info && ctrl) {
    241				memcpy(&ctrl->profile,
    242					skb->data + CAPI_MSG_BASELEN + 11,
    243					sizeof(capi_profile));
    244				session->state = BT_CONNECTED;
    245				capi_ctr_ready(ctrl);
    246			}
    247
    248			break;
    249
    250		case CAPI_FUNCTION_GET_MANUFACTURER:
    251			if (skb->len < CAPI_MSG_BASELEN + 15)
    252				break;
    253
    254			if (!info && ctrl) {
    255				int len = min_t(uint, CAPI_MANUFACTURER_LEN,
    256						skb->data[CAPI_MSG_BASELEN + 14]);
    257
    258				memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
    259				strncpy(ctrl->manu,
    260					skb->data + CAPI_MSG_BASELEN + 15, len);
    261			}
    262
    263			break;
    264
    265		case CAPI_FUNCTION_GET_VERSION:
    266			if (skb->len < CAPI_MSG_BASELEN + 32)
    267				break;
    268
    269			if (!info && ctrl) {
    270				ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
    271				ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
    272				ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
    273				ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
    274			}
    275
    276			break;
    277
    278		case CAPI_FUNCTION_GET_SERIAL_NUMBER:
    279			if (skb->len < CAPI_MSG_BASELEN + 17)
    280				break;
    281
    282			if (!info && ctrl) {
    283				int len = min_t(uint, CAPI_SERIAL_LEN,
    284						skb->data[CAPI_MSG_BASELEN + 16]);
    285
    286				memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
    287				strncpy(ctrl->serial,
    288					skb->data + CAPI_MSG_BASELEN + 17, len);
    289			}
    290
    291			break;
    292		}
    293
    294		break;
    295
    296	case CAPI_IND:
    297		if (skb->len < CAPI_MSG_BASELEN + 6)
    298			break;
    299
    300		func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
    301
    302		if (func == CAPI_FUNCTION_LOOPBACK) {
    303			int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
    304						skb->data[CAPI_MSG_BASELEN + 5]);
    305			appl = CAPIMSG_APPID(skb->data);
    306			msgnum = CAPIMSG_MSGID(skb->data);
    307			cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
    308						skb->data + CAPI_MSG_BASELEN + 6, len);
    309		}
    310
    311		break;
    312	}
    313
    314	kfree_skb(skb);
    315}
    316
    317void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
    318{
    319	struct capi_ctr *ctrl = &session->ctrl;
    320	struct cmtp_application *application;
    321	__u16 appl;
    322	__u32 contr;
    323
    324	BT_DBG("session %p skb %p len %u", session, skb, skb->len);
    325
    326	if (skb->len < CAPI_MSG_BASELEN)
    327		return;
    328
    329	if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
    330		cmtp_recv_interopmsg(session, skb);
    331		return;
    332	}
    333
    334	if (session->flags & BIT(CMTP_LOOPBACK)) {
    335		kfree_skb(skb);
    336		return;
    337	}
    338
    339	appl = CAPIMSG_APPID(skb->data);
    340	contr = CAPIMSG_CONTROL(skb->data);
    341
    342	application = cmtp_application_get(session, CMTP_MAPPING, appl);
    343	if (application) {
    344		appl = application->appl;
    345		CAPIMSG_SETAPPID(skb->data, appl);
    346	} else {
    347		BT_ERR("Can't find application with id %u", appl);
    348		kfree_skb(skb);
    349		return;
    350	}
    351
    352	if ((contr & 0x7f) == 0x01) {
    353		contr = (contr & 0xffffff80) | session->num;
    354		CAPIMSG_SETCONTROL(skb->data, contr);
    355	}
    356
    357	capi_ctr_handle_message(ctrl, appl, skb);
    358}
    359
    360static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
    361{
    362	BT_DBG("ctrl %p data %p", ctrl, data);
    363
    364	return 0;
    365}
    366
    367static void cmtp_reset_ctr(struct capi_ctr *ctrl)
    368{
    369	struct cmtp_session *session = ctrl->driverdata;
    370
    371	BT_DBG("ctrl %p", ctrl);
    372
    373	capi_ctr_down(ctrl);
    374
    375	atomic_inc(&session->terminate);
    376	wake_up_process(session->task);
    377}
    378
    379static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
    380{
    381	DECLARE_WAITQUEUE(wait, current);
    382	struct cmtp_session *session = ctrl->driverdata;
    383	struct cmtp_application *application;
    384	unsigned long timeo = CMTP_INTEROP_TIMEOUT;
    385	unsigned char buf[8];
    386	int err = 0, nconn, want = rp->level3cnt;
    387
    388	BT_DBG("ctrl %p appl %u level3cnt %u datablkcnt %u datablklen %u",
    389	       ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
    390
    391	application = cmtp_application_add(session, appl);
    392	if (!application) {
    393		BT_ERR("Can't allocate memory for new application");
    394		return;
    395	}
    396
    397	if (want < 0)
    398		nconn = ctrl->profile.nbchannel * -want;
    399	else
    400		nconn = want;
    401
    402	if (nconn == 0)
    403		nconn = ctrl->profile.nbchannel;
    404
    405	capimsg_setu16(buf, 0, nconn);
    406	capimsg_setu16(buf, 2, rp->datablkcnt);
    407	capimsg_setu16(buf, 4, rp->datablklen);
    408
    409	application->state = BT_CONFIG;
    410	application->msgnum = cmtp_msgnum_get(session);
    411
    412	cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
    413				CAPI_FUNCTION_REGISTER, buf, 6);
    414
    415	add_wait_queue(&session->wait, &wait);
    416	while (1) {
    417		set_current_state(TASK_INTERRUPTIBLE);
    418
    419		if (!timeo) {
    420			err = -EAGAIN;
    421			break;
    422		}
    423
    424		if (application->state == BT_CLOSED) {
    425			err = -application->err;
    426			break;
    427		}
    428
    429		if (application->state == BT_CONNECTED)
    430			break;
    431
    432		if (signal_pending(current)) {
    433			err = -EINTR;
    434			break;
    435		}
    436
    437		timeo = schedule_timeout(timeo);
    438	}
    439	set_current_state(TASK_RUNNING);
    440	remove_wait_queue(&session->wait, &wait);
    441
    442	if (err) {
    443		cmtp_application_del(session, application);
    444		return;
    445	}
    446}
    447
    448static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
    449{
    450	struct cmtp_session *session = ctrl->driverdata;
    451	struct cmtp_application *application;
    452
    453	BT_DBG("ctrl %p appl %u", ctrl, appl);
    454
    455	application = cmtp_application_get(session, CMTP_APPLID, appl);
    456	if (!application) {
    457		BT_ERR("Can't find application");
    458		return;
    459	}
    460
    461	application->msgnum = cmtp_msgnum_get(session);
    462
    463	cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
    464				CAPI_FUNCTION_RELEASE, NULL, 0);
    465
    466	wait_event_interruptible_timeout(session->wait,
    467			(application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
    468
    469	cmtp_application_del(session, application);
    470}
    471
    472static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
    473{
    474	struct cmtp_session *session = ctrl->driverdata;
    475	struct cmtp_application *application;
    476	__u16 appl;
    477	__u32 contr;
    478
    479	BT_DBG("ctrl %p skb %p", ctrl, skb);
    480
    481	appl = CAPIMSG_APPID(skb->data);
    482	contr = CAPIMSG_CONTROL(skb->data);
    483
    484	application = cmtp_application_get(session, CMTP_APPLID, appl);
    485	if ((!application) || (application->state != BT_CONNECTED)) {
    486		BT_ERR("Can't find application with id %u", appl);
    487		return CAPI_ILLAPPNR;
    488	}
    489
    490	CAPIMSG_SETAPPID(skb->data, application->mapping);
    491
    492	if ((contr & 0x7f) == session->num) {
    493		contr = (contr & 0xffffff80) | 0x01;
    494		CAPIMSG_SETCONTROL(skb->data, contr);
    495	}
    496
    497	cmtp_send_capimsg(session, skb);
    498
    499	return CAPI_NOERROR;
    500}
    501
    502static char *cmtp_procinfo(struct capi_ctr *ctrl)
    503{
    504	return "CAPI Message Transport Protocol";
    505}
    506
    507static int cmtp_proc_show(struct seq_file *m, void *v)
    508{
    509	struct capi_ctr *ctrl = m->private;
    510	struct cmtp_session *session = ctrl->driverdata;
    511	struct cmtp_application *app;
    512
    513	seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
    514	seq_printf(m, "addr %s\n", session->name);
    515	seq_printf(m, "ctrl %d\n", session->num);
    516
    517	list_for_each_entry(app, &session->applications, list) {
    518		seq_printf(m, "appl %u -> %u\n", app->appl, app->mapping);
    519	}
    520
    521	return 0;
    522}
    523
    524int cmtp_attach_device(struct cmtp_session *session)
    525{
    526	unsigned char buf[4];
    527	long ret;
    528
    529	BT_DBG("session %p", session);
    530
    531	capimsg_setu32(buf, 0, 0);
    532
    533	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
    534				CAPI_FUNCTION_GET_PROFILE, buf, 4);
    535
    536	ret = wait_event_interruptible_timeout(session->wait,
    537			session->ncontroller, CMTP_INTEROP_TIMEOUT);
    538
    539	BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
    540
    541	if (!ret)
    542		return -ETIMEDOUT;
    543
    544	if (!session->ncontroller)
    545		return -ENODEV;
    546
    547	if (session->ncontroller > 1)
    548		BT_INFO("Setting up only CAPI controller 1");
    549
    550	session->ctrl.owner      = THIS_MODULE;
    551	session->ctrl.driverdata = session;
    552	strcpy(session->ctrl.name, session->name);
    553
    554	session->ctrl.driver_name   = "cmtp";
    555	session->ctrl.load_firmware = cmtp_load_firmware;
    556	session->ctrl.reset_ctr     = cmtp_reset_ctr;
    557	session->ctrl.register_appl = cmtp_register_appl;
    558	session->ctrl.release_appl  = cmtp_release_appl;
    559	session->ctrl.send_message  = cmtp_send_message;
    560
    561	session->ctrl.procinfo      = cmtp_procinfo;
    562	session->ctrl.proc_show     = cmtp_proc_show;
    563
    564	if (attach_capi_ctr(&session->ctrl) < 0) {
    565		BT_ERR("Can't attach new controller");
    566		return -EBUSY;
    567	}
    568
    569	session->num = session->ctrl.cnr;
    570
    571	BT_DBG("session %p num %d", session, session->num);
    572
    573	capimsg_setu32(buf, 0, 1);
    574
    575	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
    576				CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
    577
    578	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
    579				CAPI_FUNCTION_GET_VERSION, buf, 4);
    580
    581	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
    582				CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
    583
    584	cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
    585				CAPI_FUNCTION_GET_PROFILE, buf, 4);
    586
    587	return 0;
    588}
    589
    590void cmtp_detach_device(struct cmtp_session *session)
    591{
    592	BT_DBG("session %p", session);
    593
    594	detach_capi_ctr(&session->ctrl);
    595}