mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
168fe32a07
Pull poll annotations from Al Viro: "This introduces a __bitwise type for POLL### bitmap, and propagates the annotations through the tree. Most of that stuff is as simple as 'make ->poll() instances return __poll_t and do the same to local variables used to hold the future return value'. Some of the obvious brainos found in process are fixed (e.g. POLLIN misspelled as POLL_IN). At that point the amount of sparse warnings is low and most of them are for genuine bugs - e.g. ->poll() instance deciding to return -EINVAL instead of a bitmap. I hadn't touched those in this series - it's large enough as it is. Another problem it has caught was eventpoll() ABI mess; select.c and eventpoll.c assumed that corresponding POLL### and EPOLL### were equal. That's true for some, but not all of them - EPOLL### are arch-independent, but POLL### are not. The last commit in this series separates userland POLL### values from the (now arch-independent) kernel-side ones, converting between them in the few places where they are copied to/from userland. AFAICS, this is the least disruptive fix preserving poll(2) ABI and making epoll() work on all architectures. As it is, it's simply broken on sparc - try to give it EPOLLWRNORM and it will trigger only on what would've triggered EPOLLWRBAND on other architectures. EPOLLWRBAND and EPOLLRDHUP, OTOH, are never triggered at all on sparc. With this patch they should work consistently on all architectures" * 'misc.poll' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (37 commits) make kernel-side POLL... arch-independent eventpoll: no need to mask the result of epi_item_poll() again eventpoll: constify struct epoll_event pointers debugging printk in sg_poll() uses %x to print POLL... bitmap annotate poll(2) guts 9p: untangle ->poll() mess ->si_band gets POLL... bitmap stored into a user-visible long field ring_buffer_poll_wait() return value used as return value of ->poll() the rest of drivers/*: annotate ->poll() instances media: annotate ->poll() instances fs: annotate ->poll() instances ipc, kernel, mm: annotate ->poll() instances net: annotate ->poll() instances apparmor: annotate ->poll() instances tomoyo: annotate ->poll() instances sound: annotate ->poll() instances acpi: annotate ->poll() instances crypto: annotate ->poll() instances block: annotate ->poll() instances x86: annotate ->poll() instances ...
257 lines
7.0 KiB
C
257 lines
7.0 KiB
C
/*
|
|
* if_alg: User-space algorithm interface
|
|
*
|
|
* Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
*/
|
|
|
|
#ifndef _CRYPTO_IF_ALG_H
|
|
#define _CRYPTO_IF_ALG_H
|
|
|
|
#include <linux/compiler.h>
|
|
#include <linux/completion.h>
|
|
#include <linux/if_alg.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/types.h>
|
|
#include <linux/atomic.h>
|
|
#include <net/sock.h>
|
|
|
|
#include <crypto/aead.h>
|
|
#include <crypto/skcipher.h>
|
|
|
|
#define ALG_MAX_PAGES 16
|
|
|
|
struct crypto_async_request;
|
|
|
|
struct alg_sock {
|
|
/* struct sock must be the first member of struct alg_sock */
|
|
struct sock sk;
|
|
|
|
struct sock *parent;
|
|
|
|
unsigned int refcnt;
|
|
unsigned int nokey_refcnt;
|
|
|
|
const struct af_alg_type *type;
|
|
void *private;
|
|
};
|
|
|
|
struct af_alg_control {
|
|
struct af_alg_iv *iv;
|
|
int op;
|
|
unsigned int aead_assoclen;
|
|
};
|
|
|
|
struct af_alg_type {
|
|
void *(*bind)(const char *name, u32 type, u32 mask);
|
|
void (*release)(void *private);
|
|
int (*setkey)(void *private, const u8 *key, unsigned int keylen);
|
|
int (*accept)(void *private, struct sock *sk);
|
|
int (*accept_nokey)(void *private, struct sock *sk);
|
|
int (*setauthsize)(void *private, unsigned int authsize);
|
|
|
|
struct proto_ops *ops;
|
|
struct proto_ops *ops_nokey;
|
|
struct module *owner;
|
|
char name[14];
|
|
};
|
|
|
|
struct af_alg_sgl {
|
|
struct scatterlist sg[ALG_MAX_PAGES + 1];
|
|
struct page *pages[ALG_MAX_PAGES];
|
|
unsigned int npages;
|
|
};
|
|
|
|
/* TX SGL entry */
|
|
struct af_alg_tsgl {
|
|
struct list_head list;
|
|
unsigned int cur; /* Last processed SG entry */
|
|
struct scatterlist sg[0]; /* Array of SGs forming the SGL */
|
|
};
|
|
|
|
#define MAX_SGL_ENTS ((4096 - sizeof(struct af_alg_tsgl)) / \
|
|
sizeof(struct scatterlist) - 1)
|
|
|
|
/* RX SGL entry */
|
|
struct af_alg_rsgl {
|
|
struct af_alg_sgl sgl;
|
|
struct list_head list;
|
|
size_t sg_num_bytes; /* Bytes of data in that SGL */
|
|
};
|
|
|
|
/**
|
|
* struct af_alg_async_req - definition of crypto request
|
|
* @iocb: IOCB for AIO operations
|
|
* @sk: Socket the request is associated with
|
|
* @first_rsgl: First RX SG
|
|
* @last_rsgl: Pointer to last RX SG
|
|
* @rsgl_list: Track RX SGs
|
|
* @tsgl: Private, per request TX SGL of buffers to process
|
|
* @tsgl_entries: Number of entries in priv. TX SGL
|
|
* @outlen: Number of output bytes generated by crypto op
|
|
* @areqlen: Length of this data structure
|
|
* @cra_u: Cipher request
|
|
*/
|
|
struct af_alg_async_req {
|
|
struct kiocb *iocb;
|
|
struct sock *sk;
|
|
|
|
struct af_alg_rsgl first_rsgl;
|
|
struct af_alg_rsgl *last_rsgl;
|
|
struct list_head rsgl_list;
|
|
|
|
struct scatterlist *tsgl;
|
|
unsigned int tsgl_entries;
|
|
|
|
unsigned int outlen;
|
|
unsigned int areqlen;
|
|
|
|
union {
|
|
struct aead_request aead_req;
|
|
struct skcipher_request skcipher_req;
|
|
} cra_u;
|
|
|
|
/* req ctx trails this struct */
|
|
};
|
|
|
|
/**
|
|
* struct af_alg_ctx - definition of the crypto context
|
|
*
|
|
* The crypto context tracks the input data during the lifetime of an AF_ALG
|
|
* socket.
|
|
*
|
|
* @tsgl_list: Link to TX SGL
|
|
* @iv: IV for cipher operation
|
|
* @aead_assoclen: Length of AAD for AEAD cipher operations
|
|
* @completion: Work queue for synchronous operation
|
|
* @used: TX bytes sent to kernel. This variable is used to
|
|
* ensure that user space cannot cause the kernel
|
|
* to allocate too much memory in sendmsg operation.
|
|
* @rcvused: Total RX bytes to be filled by kernel. This variable
|
|
* is used to ensure user space cannot cause the kernel
|
|
* to allocate too much memory in a recvmsg operation.
|
|
* @more: More data to be expected from user space?
|
|
* @merge: Shall new data from user space be merged into existing
|
|
* SG?
|
|
* @enc: Cryptographic operation to be performed when
|
|
* recvmsg is invoked.
|
|
* @len: Length of memory allocated for this data structure.
|
|
*/
|
|
struct af_alg_ctx {
|
|
struct list_head tsgl_list;
|
|
|
|
void *iv;
|
|
size_t aead_assoclen;
|
|
|
|
struct crypto_wait wait;
|
|
|
|
size_t used;
|
|
atomic_t rcvused;
|
|
|
|
bool more;
|
|
bool merge;
|
|
bool enc;
|
|
|
|
unsigned int len;
|
|
};
|
|
|
|
int af_alg_register_type(const struct af_alg_type *type);
|
|
int af_alg_unregister_type(const struct af_alg_type *type);
|
|
|
|
int af_alg_release(struct socket *sock);
|
|
void af_alg_release_parent(struct sock *sk);
|
|
int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern);
|
|
|
|
int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len);
|
|
void af_alg_free_sg(struct af_alg_sgl *sgl);
|
|
void af_alg_link_sg(struct af_alg_sgl *sgl_prev, struct af_alg_sgl *sgl_new);
|
|
|
|
int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con);
|
|
|
|
static inline struct alg_sock *alg_sk(struct sock *sk)
|
|
{
|
|
return (struct alg_sock *)sk;
|
|
}
|
|
|
|
/**
|
|
* Size of available buffer for sending data from user space to kernel.
|
|
*
|
|
* @sk socket of connection to user space
|
|
* @return number of bytes still available
|
|
*/
|
|
static inline int af_alg_sndbuf(struct sock *sk)
|
|
{
|
|
struct alg_sock *ask = alg_sk(sk);
|
|
struct af_alg_ctx *ctx = ask->private;
|
|
|
|
return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) -
|
|
ctx->used, 0);
|
|
}
|
|
|
|
/**
|
|
* Can the send buffer still be written to?
|
|
*
|
|
* @sk socket of connection to user space
|
|
* @return true => writable, false => not writable
|
|
*/
|
|
static inline bool af_alg_writable(struct sock *sk)
|
|
{
|
|
return PAGE_SIZE <= af_alg_sndbuf(sk);
|
|
}
|
|
|
|
/**
|
|
* Size of available buffer used by kernel for the RX user space operation.
|
|
*
|
|
* @sk socket of connection to user space
|
|
* @return number of bytes still available
|
|
*/
|
|
static inline int af_alg_rcvbuf(struct sock *sk)
|
|
{
|
|
struct alg_sock *ask = alg_sk(sk);
|
|
struct af_alg_ctx *ctx = ask->private;
|
|
|
|
return max_t(int, max_t(int, sk->sk_rcvbuf & PAGE_MASK, PAGE_SIZE) -
|
|
atomic_read(&ctx->rcvused), 0);
|
|
}
|
|
|
|
/**
|
|
* Can the RX buffer still be written to?
|
|
*
|
|
* @sk socket of connection to user space
|
|
* @return true => writable, false => not writable
|
|
*/
|
|
static inline bool af_alg_readable(struct sock *sk)
|
|
{
|
|
return PAGE_SIZE <= af_alg_rcvbuf(sk);
|
|
}
|
|
|
|
int af_alg_alloc_tsgl(struct sock *sk);
|
|
unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset);
|
|
void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
|
|
size_t dst_offset);
|
|
void af_alg_free_areq_sgls(struct af_alg_async_req *areq);
|
|
int af_alg_wait_for_wmem(struct sock *sk, unsigned int flags);
|
|
void af_alg_wmem_wakeup(struct sock *sk);
|
|
int af_alg_wait_for_data(struct sock *sk, unsigned flags);
|
|
void af_alg_data_wakeup(struct sock *sk);
|
|
int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
|
|
unsigned int ivsize);
|
|
ssize_t af_alg_sendpage(struct socket *sock, struct page *page,
|
|
int offset, size_t size, int flags);
|
|
void af_alg_free_resources(struct af_alg_async_req *areq);
|
|
void af_alg_async_cb(struct crypto_async_request *_req, int err);
|
|
__poll_t af_alg_poll(struct file *file, struct socket *sock,
|
|
poll_table *wait);
|
|
struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk,
|
|
unsigned int areqlen);
|
|
int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
|
|
struct af_alg_async_req *areq, size_t maxsize,
|
|
size_t *outlen);
|
|
|
|
#endif /* _CRYPTO_IF_ALG_H */
|