Skip to content
Open
3 changes: 0 additions & 3 deletions include/net/rpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ static inline int rpl_init(void)
static inline void rpl_exit(void) {}
#endif

/* Worst decompression memory usage ipv6 address (16) + pad 7 */
#define IPV6_RPL_SRH_WORST_SWAP_SIZE (sizeof(struct in6_addr) + 7)

size_t ipv6_rpl_srh_size(unsigned char n, unsigned char cmpri,
unsigned char cmpre);

Expand Down
5 changes: 0 additions & 5 deletions include/net/tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ struct tls_sw_context_tx {
struct tls_rec *open_rec;
struct list_head tx_list;
atomic_t encrypt_pending;
/* protect crypto_wait with encrypt_pending */
spinlock_t encrypt_compl_lock;
int async_notify;
u8 async_capable:1;

#define BIT_TX_SCHEDULED 0
Expand Down Expand Up @@ -136,8 +133,6 @@ struct tls_sw_context_rx {
struct tls_strparser strp;

atomic_t decrypt_pending;
/* protect crypto_wait with decrypt_pending*/
spinlock_t decrypt_compl_lock;
struct sk_buff_head async_hold;
struct wait_queue_head wq;
};
Expand Down
34 changes: 15 additions & 19 deletions net/ipv6/exthdrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
struct inet6_dev *idev;
struct ipv6hdr *oldhdr;
struct in6_addr addr;
unsigned int chdr_len;
unsigned char *buf;
int accept_rpl_seg;
int i, err;
Expand Down Expand Up @@ -559,24 +560,6 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
return -1;
}

if (skb_cloned(skb)) {
if (pskb_expand_head(skb, IPV6_RPL_SRH_WORST_SWAP_SIZE, 0,
GFP_ATOMIC)) {
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
IPSTATS_MIB_OUTDISCARDS);
kfree_skb(skb);
return -1;
}
} else {
err = skb_cow_head(skb, IPV6_RPL_SRH_WORST_SWAP_SIZE);
if (unlikely(err)) {
kfree_skb(skb);
return -1;
}
}

hdr = (struct ipv6_rpl_sr_hdr *)skb_transport_header(skb);

if (!pskb_may_pull(skb, ipv6_rpl_srh_size(n, hdr->cmpri,
hdr->cmpre))) {
kfree_skb(skb);
Expand Down Expand Up @@ -622,7 +605,20 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
skb_pull(skb, ((hdr->hdrlen + 1) << 3));
skb_postpull_rcsum(skb, oldhdr,
sizeof(struct ipv6hdr) + ((hdr->hdrlen + 1) << 3));
skb_push(skb, ((chdr->hdrlen + 1) << 3) + sizeof(struct ipv6hdr));
chdr_len = sizeof(struct ipv6hdr) + ((chdr->hdrlen + 1) << 3);
if (unlikely(!hdr->segments_left ||
skb_headroom(skb) < chdr_len + skb->mac_len)) {
if (pskb_expand_head(skb, chdr_len + skb->mac_len, 0,
GFP_ATOMIC)) {
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTDISCARDS);
kfree_skb(skb);
kfree(buf);
return -1;
}

oldhdr = ipv6_hdr(skb);
}
skb_push(skb, chdr_len);
skb_reset_network_header(skb);
skb_mac_header_rebuild(skb);
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/ipset/ip_set_hash_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
if (!test_bit(i, n->used))
k++;
}
if (n->pos == 0 && k == 0) {
if (k == n->pos) {
t->hregion[r].ext_size -= ext_size(n->size, dsize);
rcu_assign_pointer(hbucket(t, key), NULL);
kfree_rcu(n, rcu);
Expand Down
33 changes: 20 additions & 13 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,6 @@ static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
nft_set_elem_change_active(ctx->net, set, ext);
elem.priv = catchall->elem;
nft_setelem_data_deactivate(ctx->net, set, &elem);
break;
}
}

Expand Down Expand Up @@ -2399,8 +2398,10 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
rcu_assign_pointer(chain->rules_gen_1, rules);

err = nf_tables_register_hook(net, table, chain);
if (err < 0)
if (err < 0) {
synchronize_rcu();
goto err_destroy_chain;
}

if (!nft_use_inc(&table->use)) {
err = -EMFILE;
Expand Down Expand Up @@ -2429,6 +2430,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
nft_use_dec_restore(&table->use);
err_use:
nf_tables_unregister_hook(net, table, chain);
synchronize_rcu();
err_destroy_chain:
nf_tables_chain_destroy(ctx);

Expand Down Expand Up @@ -5142,7 +5144,6 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx,
nft_clear(ctx->net, ext);
elem.priv = catchall->elem;
nft_setelem_data_activate(ctx->net, set, &elem);
break;
}
}

Expand Down Expand Up @@ -6271,6 +6272,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
struct nft_data_desc desc;
enum nft_registers dreg;
struct nft_trans *trans;
bool set_full = false;
u64 timeout;
u64 expiration;
int err, i;
Expand Down Expand Up @@ -6557,10 +6559,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (err < 0)
goto err_elem_free;

if (!(flags & NFT_SET_ELEM_CATCHALL) && set->size) {
unsigned int max = set->size + set->ndeact, nelems;

nelems = atomic_inc_return(&set->nelems);
if (nelems > max)
set_full = true;
}

trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
if (trans == NULL) {
err = -ENOMEM;
goto err_elem_free;
goto err_set_size;
}

ext->genmask = nft_genmask_cur(ctx->net);
Expand Down Expand Up @@ -6592,20 +6602,16 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
goto err_element_clash;
}

if (!(flags & NFT_SET_ELEM_CATCHALL) && set->size &&
!atomic_add_unless(&set->nelems, 1, set->size + set->ndeact)) {
err = -ENFILE;
goto err_set_full;
}

nft_trans_elem(trans) = elem;
nft_trans_commit_list_add_tail(ctx->net, trans);
return 0;

err_set_full:
nft_setelem_remove(ctx->net, set, &elem);
return set_full ? -ENFILE : 0;

err_element_clash:
kfree(trans);
err_set_size:
if (!(flags & NFT_SET_ELEM_CATCHALL) && set->size)
atomic_dec(&set->nelems);
err_elem_free:
nf_tables_set_elem_destroy(ctx, set, elem.priv);
err_parse_data:
Expand Down Expand Up @@ -8105,6 +8111,7 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
kfree_rcu(hook, rcu);
}
err4:
synchronize_rcu();
flowtable->data.type->free(&flowtable->data);
err3:
module_put(type->owner);
Expand Down
6 changes: 6 additions & 0 deletions net/netfilter/xt_IDLETIMER.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par)

info->timer = __idletimer_tg_find_by_label(info->label);
if (info->timer) {
if (info->timer->timer_type & XT_IDLETIMER_ALARM) {
pr_debug("Adding/Replacing rule with same label and different timer type is not allowed\n");
mutex_unlock(&list_mutex);
return -EINVAL;
}

info->timer->refcnt++;
mod_timer(&info->timer->timer,
msecs_to_jiffies(info->timeout * 1000) + jiffies);
Expand Down
51 changes: 13 additions & 38 deletions net/tls/tls_sw.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,8 @@ static void tls_decrypt_done(struct crypto_async_request *req, int err)

kfree(aead_req);

spin_lock_bh(&ctx->decrypt_compl_lock);
if (!atomic_dec_return(&ctx->decrypt_pending))
if (atomic_dec_and_test(&ctx->decrypt_pending))
complete(&ctx->async_wait.completion);
spin_unlock_bh(&ctx->decrypt_compl_lock);
}

static int tls_do_decryption(struct sock *sk,
Expand All @@ -241,6 +239,7 @@ static int tls_do_decryption(struct sock *sk,
aead_request_set_callback(aead_req,
CRYPTO_TFM_REQ_MAY_BACKLOG,
tls_decrypt_done, sk);
DEBUG_NET_WARN_ON_ONCE(atomic_read(&ctx->decrypt_pending) < 1);
atomic_inc(&ctx->decrypt_pending);
} else {
aead_request_set_callback(aead_req,
Expand Down Expand Up @@ -427,7 +426,6 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err)
struct scatterlist *sge;
struct sk_msg *msg_en;
struct tls_rec *rec;
int pending;

rec = container_of(aead_req, struct tls_rec, aead_req);
msg_en = &rec->msg_encrypted;
Expand Down Expand Up @@ -466,12 +464,8 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err)
}
}

spin_lock_bh(&ctx->encrypt_compl_lock);
pending = atomic_dec_return(&ctx->encrypt_pending);

if (!pending && ctx->async_notify)
if (atomic_dec_and_test(&ctx->encrypt_pending))
complete(&ctx->async_wait.completion);
spin_unlock_bh(&ctx->encrypt_compl_lock);
}

static int tls_do_encryption(struct sock *sk,
Expand Down Expand Up @@ -520,6 +514,7 @@ static int tls_do_encryption(struct sock *sk,

/* Add the record in tx_list */
list_add_tail((struct list_head *)&rec->list, &ctx->tx_list);
DEBUG_NET_WARN_ON_ONCE(atomic_read(&ctx->encrypt_pending) < 1);
atomic_inc(&ctx->encrypt_pending);

rc = crypto_aead_encrypt(aead_req);
Expand Down Expand Up @@ -929,7 +924,6 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
int num_zc = 0;
int orig_size;
int ret = 0;
int pending;

if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL |
MSG_CMSG_COMPAT))
Expand Down Expand Up @@ -1097,20 +1091,9 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
goto send_end;
} else if (num_zc) {
/* Wait for pending encryptions to get completed */
spin_lock_bh(&ctx->encrypt_compl_lock);
ctx->async_notify = true;

pending = atomic_read(&ctx->encrypt_pending);
spin_unlock_bh(&ctx->encrypt_compl_lock);
if (pending)
if (!atomic_dec_and_test(&ctx->encrypt_pending))
crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
else
reinit_completion(&ctx->async_wait.completion);

/* There can be no concurrent accesses, since we have no
* pending encrypt operations
*/
WRITE_ONCE(ctx->async_notify, false);
atomic_inc(&ctx->encrypt_pending);

if (ctx->async_wait.err) {
ret = ctx->async_wait.err;
Expand Down Expand Up @@ -2096,16 +2079,13 @@ int tls_sw_recvmsg(struct sock *sk,

recv_end:
if (async) {
int ret, pending;
int ret;

/* Wait for all previously submitted records to be decrypted */
spin_lock_bh(&ctx->decrypt_compl_lock);
reinit_completion(&ctx->async_wait.completion);
pending = atomic_read(&ctx->decrypt_pending);
spin_unlock_bh(&ctx->decrypt_compl_lock);
ret = 0;
if (pending)
if (!atomic_dec_and_test(&ctx->decrypt_pending))
ret = crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
atomic_inc(&ctx->decrypt_pending);
__skb_queue_purge(&ctx->async_hold);

if (ret) {
Expand Down Expand Up @@ -2322,16 +2302,11 @@ void tls_sw_release_resources_tx(struct sock *sk)
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
struct tls_rec *rec, *tmp;
int pending;

/* Wait for any pending async encryptions to complete */
spin_lock_bh(&ctx->encrypt_compl_lock);
ctx->async_notify = true;
pending = atomic_read(&ctx->encrypt_pending);
spin_unlock_bh(&ctx->encrypt_compl_lock);

if (pending)
if (!atomic_dec_and_test(&ctx->encrypt_pending))
crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
atomic_inc(&ctx->encrypt_pending);

tls_tx_records(sk, -1);

Expand Down Expand Up @@ -2524,7 +2499,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)

if (tx) {
crypto_init_wait(&sw_ctx_tx->async_wait);
spin_lock_init(&sw_ctx_tx->encrypt_compl_lock);
atomic_set(&sw_ctx_tx->encrypt_pending, 1);
crypto_info = &ctx->crypto_send.info;
cctx = &ctx->tx;
aead = &sw_ctx_tx->aead_send;
Expand All @@ -2533,7 +2508,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
sw_ctx_tx->tx_work.sk = sk;
} else {
crypto_init_wait(&sw_ctx_rx->async_wait);
spin_lock_init(&sw_ctx_rx->decrypt_compl_lock);
atomic_set(&sw_ctx_rx->decrypt_pending, 1);
init_waitqueue_head(&sw_ctx_rx->wq);
crypto_info = &ctx->crypto_recv.info;
cctx = &ctx->rx;
Expand Down
Loading