summaryrefslogtreecommitdiffstats
path: root/crypto/userspace/ncr-limits.c
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-07-22 16:15:04 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-07-22 17:29:25 +0200
commit893a38ffe67459db005bd1c7f129c04508cd015d (patch)
tree43dd0080073ffec9cb66320e13cbbe9224a85b42 /crypto/userspace/ncr-limits.c
parent619da468b62aed1c15fd81a4f630bcbb7c12dd7d (diff)
downloadkernel-crypto-893a38ffe67459db005bd1c7f129c04508cd015d.tar.gz
kernel-crypto-893a38ffe67459db005bd1c7f129c04508cd015d.tar.xz
kernel-crypto-893a38ffe67459db005bd1c7f129c04508cd015d.zip
Rename/delete files to fit into the kernel.
No files are modified in this commit - this is a "bridge" for allowing merges between standalone and integrated work.
Diffstat (limited to 'crypto/userspace/ncr-limits.c')
-rw-r--r--crypto/userspace/ncr-limits.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/crypto/userspace/ncr-limits.c b/crypto/userspace/ncr-limits.c
new file mode 100644
index 00000000000..746434c5d1b
--- /dev/null
+++ b/crypto/userspace/ncr-limits.c
@@ -0,0 +1,199 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Nikos Mavrogiannopoulos <nmav@gnutls.org>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * cryptodev 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * cryptodev is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/random.h>
+#include "cryptodev.h"
+#include <asm/atomic.h>
+#include <linux/version.h>
+#include <linux/file.h>
+#include <linux/cred.h>
+#include "ncr.h"
+#include "ncr_int.h"
+
+/* arbitrary now */
+static unsigned int max_per_user[] = {
+ [LIMIT_TYPE_KEY] = 128,
+ [LIMIT_TYPE_DATA] = 128,
+};
+
+static unsigned int max_per_process[] = {
+ [LIMIT_TYPE_KEY] = 64,
+ [LIMIT_TYPE_DATA] = 64,
+};
+
+struct limit_user_item_st {
+ struct list_head list;
+ uid_t uid;
+ limits_type_t type;
+ atomic_t cnt;
+};
+
+struct limit_process_item_st {
+ struct list_head list;
+ pid_t pid;
+ limits_type_t type;
+ atomic_t cnt;
+};
+
+struct limit_st {
+ struct list_sem_st users;
+ struct list_sem_st processes;
+};
+
+static struct limit_st limits;
+
+void ncr_limits_init(void)
+{
+ init_MUTEX(&limits.users.sem);
+ INIT_LIST_HEAD(&limits.users.list);
+
+ init_MUTEX(&limits.processes.sem);
+ INIT_LIST_HEAD(&limits.processes.list);
+}
+
+void ncr_limits_deinit(void)
+{
+struct limit_process_item_st* pitem, *ptmp;
+struct limit_user_item_st* uitem, *utmp;
+
+ down(&limits.users.sem);
+ list_for_each_entry_safe(uitem, utmp, &limits.users.list, list) {
+ list_del(&uitem->list);
+ kfree(uitem);
+ }
+ up(&limits.users.sem);
+
+ down(&limits.processes.sem);
+ list_for_each_entry_safe(pitem, ptmp, &limits.processes.list, list) {
+ list_del(&pitem->list);
+ kfree(pitem);
+ }
+ up(&limits.processes.sem);
+
+}
+
+int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type)
+{
+struct limit_process_item_st* pitem;
+struct limit_user_item_st* uitem;
+int add = 1;
+int ret;
+
+ down(&limits.users.sem);
+ list_for_each_entry(uitem, &limits.users.list, list) {
+ if (uitem->uid == uid && uitem->type == type) {
+ add = 0;
+
+ if (atomic_add_unless(&uitem->cnt, 1, max_per_user[type])==0) {
+ err();
+ up(&limits.users.sem);
+ return -EPERM;
+ }
+ }
+ }
+
+ if (add) {
+ uitem = kmalloc( sizeof(*uitem), GFP_KERNEL);
+ if (uitem == NULL) {
+ err();
+ up(&limits.users.sem);
+ return -ENOMEM;
+ }
+ uitem->uid = uid;
+ uitem->type = type;
+ atomic_set(&uitem->cnt, 1);
+
+ list_add(&uitem->list, &limits.users.list);
+ }
+ up(&limits.users.sem);
+
+ add = 1;
+ /* check process limits */
+ down(&limits.processes.sem);
+ list_for_each_entry(pitem, &limits.processes.list, list) {
+ if (pitem->pid == pid && pitem->type == type) {
+ add = 0;
+ if (atomic_add_unless(&pitem->cnt, 1, max_per_process[type])==0) {
+ err();
+ up(&limits.processes.sem);
+
+ ret = -EPERM;
+ goto restore_user;
+ }
+ }
+ }
+
+
+ if (add) {
+ pitem = kmalloc(sizeof(*pitem), GFP_KERNEL);
+ if (uitem == NULL) {
+ err();
+ up(&limits.processes.sem);
+ ret = -ENOMEM;
+ goto restore_user;
+ }
+ pitem->pid = pid;
+ pitem->type = type;
+ atomic_set(&pitem->cnt, 1);
+
+ list_add(&pitem->list, &limits.processes.list);
+ }
+ up(&limits.processes.sem);
+
+ return 0;
+
+restore_user:
+ down(&limits.users.sem);
+ list_for_each_entry(uitem, &limits.users.list, list) {
+ if (uitem->uid == uid && uitem->type == type)
+ atomic_dec(&uitem->cnt);
+ }
+ up(&limits.users.sem);
+ return ret;
+}
+
+void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type)
+{
+struct limit_process_item_st* pitem;
+struct limit_user_item_st* uitem;
+
+ down(&limits.users.sem);
+ list_for_each_entry(uitem, &limits.users.list, list) {
+ if (uitem->uid == uid && uitem->type == type) {
+ atomic_dec(&uitem->cnt);
+ }
+ }
+ up(&limits.users.sem);
+
+ /* check process limits */
+ down(&limits.processes.sem);
+ list_for_each_entry(pitem, &limits.processes.list, list) {
+ if (pitem->pid == pid && pitem->type == type) {
+ atomic_dec(&pitem->cnt);
+ }
+ }
+ up(&limits.processes.sem);
+
+ return;
+}