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

sock.c (5929B)


      1/*
      2   BNEP implementation for Linux Bluetooth stack (BlueZ).
      3   Copyright (C) 2001-2002 Inventel Systemes
      4   Written 2001-2002 by
      5	David Libault  <david.libault@inventel.fr>
      6
      7   Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
      8
      9   This program is free software; you can redistribute it and/or modify
     10   it under the terms of the GNU General Public License version 2 as
     11   published by the Free Software Foundation;
     12
     13   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     14   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
     16   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
     17   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
     18   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     19   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     20   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     21
     22   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     23   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
     24   SOFTWARE IS DISCLAIMED.
     25*/
     26
     27#include <linux/compat.h>
     28#include <linux/export.h>
     29#include <linux/file.h>
     30
     31#include "bnep.h"
     32
     33static struct bt_sock_list bnep_sk_list = {
     34	.lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock)
     35};
     36
     37static int bnep_sock_release(struct socket *sock)
     38{
     39	struct sock *sk = sock->sk;
     40
     41	BT_DBG("sock %p sk %p", sock, sk);
     42
     43	if (!sk)
     44		return 0;
     45
     46	bt_sock_unlink(&bnep_sk_list, sk);
     47
     48	sock_orphan(sk);
     49	sock_put(sk);
     50	return 0;
     51}
     52
     53static int do_bnep_sock_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
     54{
     55	struct bnep_connlist_req cl;
     56	struct bnep_connadd_req  ca;
     57	struct bnep_conndel_req  cd;
     58	struct bnep_conninfo ci;
     59	struct socket *nsock;
     60	__u32 supp_feat = BIT(BNEP_SETUP_RESPONSE);
     61	int err;
     62
     63	BT_DBG("cmd %x arg %p", cmd, argp);
     64
     65	switch (cmd) {
     66	case BNEPCONNADD:
     67		if (!capable(CAP_NET_ADMIN))
     68			return -EPERM;
     69
     70		if (copy_from_user(&ca, argp, sizeof(ca)))
     71			return -EFAULT;
     72
     73		nsock = sockfd_lookup(ca.sock, &err);
     74		if (!nsock)
     75			return err;
     76
     77		if (nsock->sk->sk_state != BT_CONNECTED) {
     78			sockfd_put(nsock);
     79			return -EBADFD;
     80		}
     81		ca.device[sizeof(ca.device)-1] = 0;
     82
     83		err = bnep_add_connection(&ca, nsock);
     84		if (!err) {
     85			if (copy_to_user(argp, &ca, sizeof(ca)))
     86				err = -EFAULT;
     87		} else
     88			sockfd_put(nsock);
     89
     90		return err;
     91
     92	case BNEPCONNDEL:
     93		if (!capable(CAP_NET_ADMIN))
     94			return -EPERM;
     95
     96		if (copy_from_user(&cd, argp, sizeof(cd)))
     97			return -EFAULT;
     98
     99		return bnep_del_connection(&cd);
    100
    101	case BNEPGETCONNLIST:
    102		if (copy_from_user(&cl, argp, sizeof(cl)))
    103			return -EFAULT;
    104
    105		if (cl.cnum <= 0)
    106			return -EINVAL;
    107
    108		err = bnep_get_connlist(&cl);
    109		if (!err && copy_to_user(argp, &cl, sizeof(cl)))
    110			return -EFAULT;
    111
    112		return err;
    113
    114	case BNEPGETCONNINFO:
    115		if (copy_from_user(&ci, argp, sizeof(ci)))
    116			return -EFAULT;
    117
    118		err = bnep_get_conninfo(&ci);
    119		if (!err && copy_to_user(argp, &ci, sizeof(ci)))
    120			return -EFAULT;
    121
    122		return err;
    123
    124	case BNEPGETSUPPFEAT:
    125		if (copy_to_user(argp, &supp_feat, sizeof(supp_feat)))
    126			return -EFAULT;
    127
    128		return 0;
    129
    130	default:
    131		return -EINVAL;
    132	}
    133
    134	return 0;
    135}
    136
    137static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
    138{
    139	return do_bnep_sock_ioctl(sock, cmd, (void __user *)arg);
    140}
    141
    142#ifdef CONFIG_COMPAT
    143static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
    144{
    145	void __user *argp = compat_ptr(arg);
    146	if (cmd == BNEPGETCONNLIST) {
    147		struct bnep_connlist_req cl;
    148		unsigned __user *p = argp;
    149		u32 uci;
    150		int err;
    151
    152		if (get_user(cl.cnum, p) || get_user(uci, p + 1))
    153			return -EFAULT;
    154
    155		cl.ci = compat_ptr(uci);
    156
    157		if (cl.cnum <= 0)
    158			return -EINVAL;
    159
    160		err = bnep_get_connlist(&cl);
    161
    162		if (!err && put_user(cl.cnum, p))
    163			err = -EFAULT;
    164
    165		return err;
    166	}
    167
    168	return do_bnep_sock_ioctl(sock, cmd, argp);
    169}
    170#endif
    171
    172static const struct proto_ops bnep_sock_ops = {
    173	.family		= PF_BLUETOOTH,
    174	.owner		= THIS_MODULE,
    175	.release	= bnep_sock_release,
    176	.ioctl		= bnep_sock_ioctl,
    177#ifdef CONFIG_COMPAT
    178	.compat_ioctl	= bnep_sock_compat_ioctl,
    179#endif
    180	.bind		= sock_no_bind,
    181	.getname	= sock_no_getname,
    182	.sendmsg	= sock_no_sendmsg,
    183	.recvmsg	= sock_no_recvmsg,
    184	.listen		= sock_no_listen,
    185	.shutdown	= sock_no_shutdown,
    186	.connect	= sock_no_connect,
    187	.socketpair	= sock_no_socketpair,
    188	.accept		= sock_no_accept,
    189	.mmap		= sock_no_mmap
    190};
    191
    192static struct proto bnep_proto = {
    193	.name		= "BNEP",
    194	.owner		= THIS_MODULE,
    195	.obj_size	= sizeof(struct bt_sock)
    196};
    197
    198static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
    199			    int kern)
    200{
    201	struct sock *sk;
    202
    203	BT_DBG("sock %p", sock);
    204
    205	if (sock->type != SOCK_RAW)
    206		return -ESOCKTNOSUPPORT;
    207
    208	sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, kern);
    209	if (!sk)
    210		return -ENOMEM;
    211
    212	sock_init_data(sock, sk);
    213
    214	sock->ops = &bnep_sock_ops;
    215
    216	sock->state = SS_UNCONNECTED;
    217
    218	sock_reset_flag(sk, SOCK_ZAPPED);
    219
    220	sk->sk_protocol = protocol;
    221	sk->sk_state	= BT_OPEN;
    222
    223	bt_sock_link(&bnep_sk_list, sk);
    224	return 0;
    225}
    226
    227static const struct net_proto_family bnep_sock_family_ops = {
    228	.family = PF_BLUETOOTH,
    229	.owner	= THIS_MODULE,
    230	.create = bnep_sock_create
    231};
    232
    233int __init bnep_sock_init(void)
    234{
    235	int err;
    236
    237	err = proto_register(&bnep_proto, 0);
    238	if (err < 0)
    239		return err;
    240
    241	err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
    242	if (err < 0) {
    243		BT_ERR("Can't register BNEP socket");
    244		goto error;
    245	}
    246
    247	err = bt_procfs_init(&init_net, "bnep", &bnep_sk_list, NULL);
    248	if (err < 0) {
    249		BT_ERR("Failed to create BNEP proc file");
    250		bt_sock_unregister(BTPROTO_BNEP);
    251		goto error;
    252	}
    253
    254	BT_INFO("BNEP socket layer initialized");
    255
    256	return 0;
    257
    258error:
    259	proto_unregister(&bnep_proto);
    260	return err;
    261}
    262
    263void __exit bnep_sock_cleanup(void)
    264{
    265	bt_procfs_cleanup(&init_net, "bnep");
    266	bt_sock_unregister(BTPROTO_BNEP);
    267	proto_unregister(&bnep_proto);
    268}