SKCIPHER_REQUEST_ON_STACK details and how to use - linux-kernel

I m trying to understand what the purpose of SKCIPHER_REQUEST_ON_STACK is.
I see it being used for encrypt/decrypt operations in the kernel.
I understand it is a compiler directive and will trigger FRAME_WARN warnings.
I do not understand the macro which looks like so -
#define SKCIPHER_REQUEST_ON_STACK(name, tfm) \
char __##name##_desc[sizeof(struct skcipher_request) + \
crypto_skcipher_reqsize(tfm)] CRYPTO_MINALIGN_ATTR; \
struct skcipher_request *name = (void *)__##name##_desc`
with "CRYPTO_MINALIGN_ATTR" defined as
struct crypto_alg {
struct list_head cra_list;
struct list_head cra_users;
u32 cra_flags;
unsigned int cra_blocksize;
unsigned int cra_ctxsize;
unsigned int cra_alignmask;
int cra_priority;
atomic_t cra_refcnt;
char cra_name[CRYPTO_MAX_ALG_NAME];
char cra_driver_name[CRYPTO_MAX_ALG_NAME];
const struct crypto_type *cra_type;
union {
struct ablkcipher_alg ablkcipher;
struct blkcipher_alg blkcipher;
struct cipher_alg cipher;
struct compress_alg compress;
} cra_u;
int (*cra_init)(struct crypto_tfm *tfm);
void (*cra_exit)(struct crypto_tfm *tfm);
void (*cra_destroy)(struct crypto_alg *alg);
struct module *cra_module;
} CRYPTO_MINALIGN_ATTR;

Related

C++ Syntax of casting operators on struct object

What does the syntax of the following cast to an object Page of struct WHISPERPACKET mean
typedef struct
{
unsigned char uchData[512];
unsigned char uchType;
unsigned char uchInfo;
unsigned short unSampleRate;
unsigned short unSamples;
}WHISPERPACKET;
typedef unsigned char BYTE;
WHISPERPACKET Page;
PageBuffer = (BYTE*)&Page;
edit:
BYTE* PageBuffer;

Is there a way to create unique type Id at compile time in C++

I can create a unique type id the following way:
template<typename T>
struct TypeId
{
static size_t value()
{
return reinterpret_cast<size_t>(&TypeId<T>::value);
}
};
auto intType = TypeId<int>::value();
It works at runtime but is there a way to do it at compile time ?
I would like to use it in a switch statement like this:
switch (typeId)
{
case TypeId<int>::value():
// do something
break;
case TypeId<double>::value():
// do something
break;
case TypeId<MyClass>::value():
// do something
break;
}
The problem here is that I cannot convert a pointer to the size_t at compile time:
template<typename T>
struct TypeId
{
static constexpr size_t value()
{
return reinterpret_cast<size_t>(&TypeId<T>::value);
}
};
constexpr auto id = TypeId<int>::value();
The example above gives the following error:
error: conversion from pointer type ‘size_t (*)() {aka long unsigned int (*)()}’ to arithmetic type ‘size_t {aka long unsigned int}’ in a constant expression
constexpr auto id = TypeId<int>::value();
UPDATE
I would like to understand why returning an address is fine in a constexpr but converting it to an int is not. The following code compiles (but I cannot use pointers in a switch statement):
template<typename T>
struct TypeId
{
static constexpr void* value()
{
return reinterpret_cast<void*>(&TypeId<T>::value);
}
};
constexpr void* id = TypeId<int>::value();
std::cout << "id: " << id << std::endl;
This sounds like an XY problem. If you want to get compile-time type information, then use compile-time ways to do this. The right way to do this is with std::is_same.
if(std::is_same<int, T>::value) {
// do something
} else if (std::is_same<double, T>::value) {
// do something else
} // ...
This can cause certain problems. if you're using methods for specific types, like std::string::length() in your conditions, you'll have a compile error. There are ways to solve this:
Use if constexpr
Use std::enable_if to create template specializations that are dependent on the type
If you have only pointer-type problems, you have to reinterpret_cast all your pointers to T
There is currently no way in C++ to automatically allocate a unique integer type id and make it availabe compile time.
This is why libraries that need it use manual type registration, e.g.:
template<class T> struct TypeId;
#define REGISTER_TYPE_ID(T, id_value) template<> struct TypeId<T> { static constexpr int id = id_value; };
REGISTER_TYPE_ID(bool, 1)
REGISTER_TYPE_ID(char, 2)
REGISTER_TYPE_ID(unsigned char, 3)
REGISTER_TYPE_ID(unsigned short, 4)
REGISTER_TYPE_ID(unsigned int, 5)
REGISTER_TYPE_ID(unsigned long, 6)
REGISTER_TYPE_ID(unsigned long long, 7)
REGISTER_TYPE_ID(signed char, 8)
REGISTER_TYPE_ID(signed short, 9)
REGISTER_TYPE_ID(signed int, 10)
REGISTER_TYPE_ID(signed long, 11)
REGISTER_TYPE_ID(signed long long, 12)
REGISTER_TYPE_ID(float, 13)
REGISTER_TYPE_ID(double, 14)
REGISTER_TYPE_ID(long double, 15)

exposing a function with 2D slice as a parameter in a c-shared library (to be used in Java via JNA and C)

I am trying to write a simple matrix operations API using go and expose the APIs as a shared library. This shared library will be used from Java(using JNA) and from C.
The documentation is very sparse about using any data type beyond simple int or string as function parameters.
My requirement is to expose functions with 1 or more 2D slices as parameters AND also as return types. I am not able to figure out if such a thing is supported.
Is this possible? Are there any examples for this?
I think the key point is to have a look to the c bindings of slice,string and int generated by go build tool. I not tried 2D slice, but it should no different to 1D slice with unsafe pointer converter, maybe just be one more time allocation and convertion.
I'm not sure it's the best way, but here's the example for 1D slice:
the go part:
import "C"
//export CFoo
func CFoo(content []byte) string{
var ret []byte
//blablabla to get ret
cbuf := unsafe.Pointer(C.malloc(C.size_t(len(ret))))
C.memcpy(cbuf, unsafe.Pointer(&ret[0]), C.size_t(len(ret)))
var finalString string
hdr := (*reflect.StringHeader)(unsafe.Pointer(&finalString))
hdr.Data = uintptr(unsafe.Pointer(cbuf))
hdr.Len = len(ret)
return finalString
}
compile with -buildmode=c-shared, to get libmygo.so.
I not know JNA, expecting it like JNI. the JNI part as well as pure C part:
#include <stdio.h>
#include <jni.h>
#include <string.h>
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt32 GoInt;
typedef GoUint32 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
JNIEXPORT JNICALL jbyteArray Java_com_mynextev_infotainment_app_myev_Native_foo(JNIEnv* env, jobject obj,jbyteArray content){
JNIEnv ienv = *env;
void * Ccontent = ienv->GetByteArrayElements(env, content, 0);
int Lcontent = ienv->GetArrayLength(env, content);
GoSlice Gcontent = {Ccontent, Lcontent, Lcontent};
if(!gret.n){
printf("jni CDoAESEnc");
return NULL;
}
jbyteArray ret = ienv->NewByteArray(env, gret.n);
ienv->SetByteArrayRegion(env, ret, 0, gret.n, gret.p);
free((void*)gret.p);
ienv->ReleaseByteArrayElements(env, content, Ccontent, JNI_ABORT);
return ret;
}
build it with libmygo.so.
finally you get two so files. one for C which can be used standalone; one for Java which must be used with libmygo.so together.

Compiler error, with 3.0.101 kernel using gcc 4.9

Here is the error
fs/fat/dir.c: In function 'fat_dir_empty':
fs/fat/dir.c:124:8: warning: 'de' may be used uninitialized in this function [-Wmaybe-uninitialized]
error, forbidden warning: dir.c:124
static inline int fat_get_entry(struct inode *dir, loff_t *pos,
struct buffer_head **bh,
struct msdos_dir_entry **de)
{
/* Fast stuff first */
if (*bh && *de &&
(*de - (struct msdos_dir_entry *)(*bh)->b_data) <
MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
*pos += sizeof(struct msdos_dir_entry);
(*de)++;
return 0;
}
return fat__get_entry(dir, pos, bh, de);
}
(*de)++; is the issue
I don't understand, 3.4 with same coding compiles just fine. Any help with this would be appreciated.
UPDATE:
After reading, http://lwn.net/Articles/529954/
I was running with -O3 optimization, which effects -Wmaybe-uninitialized
UPDATE 2:
vfat builds as a module, no problem. Only have issue as a built-in. I wonder why that would be?
Patch from Code Aurora Forum fixes this.
From: David Brown
Date: Sun, 10 Oct 2010 23:34:20 -0700
Subject: [PATCH] FAT: Fix warning
fs/fat/dir.c:43: warning: 'de' may be used uninitialized in this function
The complexity of the code flow makes this seem possible. Initialize
the value to NULL to eliminate the compiler warning. This only masks
the warning, since if the value were unused, there would still be a
NULL pointer.
Change-Id: I9fc36abace09409853b63e0997328b75ce703769
Signed-off-by: David Brown <davidb#codeaurora.org>
---
fs/fat/dir.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 65e174b..409b3ce 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
## -343,7 +343,7 ## int fat_search_long(struct inode *inode, const unsigned char *name,
struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh = NULL;
- struct msdos_dir_entry *de;
+ struct msdos_dir_entry *de = NULL;
struct nls_table *nls_disk = sbi->nls_disk;
unsigned char nr_slots;
wchar_t bufuname[14];
## -468,7 +468,7 ## static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh;
- struct msdos_dir_entry *de;
+ struct msdos_dir_entry *de = NULL;
struct nls_table *nls_disk = sbi->nls_disk;
unsigned char nr_slots;
wchar_t bufuname[14];
## -887,7 +887,7 ## EXPORT_SYMBOL_GPL(fat_get_dotdot_entry);
int fat_dir_empty(struct inode *dir)
{
struct buffer_head *bh;
- struct msdos_dir_entry *de;
+ struct msdos_dir_entry *de = NULL;
loff_t cpos;
int result = 0;
## -913,7 +913,7 ## EXPORT_SYMBOL_GPL(fat_dir_empty);
int fat_subdirs(struct inode *dir)
{
struct buffer_head *bh;
- struct msdos_dir_entry *de;
+ struct msdos_dir_entry *de = NULL;
loff_t cpos;
int count = 0;
## -1240,7 +1240,7 ## int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
struct super_block *sb = dir->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */
- struct msdos_dir_entry *uninitialized_var(de);
+ struct msdos_dir_entry *de = NULL;
int err, free_slots, i, nr_bhs;
loff_t pos, i_pos;
--
2.5.0

inode_operations , warning: initialization from incompatible pointer type

I'm trying to compile a simple Kernel program that read and write from a proc file.
I'm trying to set permission to that file by overriding the permission fp in inode_operations struct (.permission)
static int module_permission(struct inode *inode, int op, struct nameidata *foo)
{
. . .
}
static struct inode_operations Inode_Ops_4_Our_Proc_File = {
.permission = module_permission, /* check for permissions */
};
Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File;
For some reason, when I compile this i get -> warning: initialization from incompatible pointer type on the following line:
.permission = module_permission, /* check for permissions */
Any idea how to solve this?
Thanks!
What kernel version are you using ? I am on 2.6.33 and this is how inode_operations is declared :
struct inode_operations {
...
int (*permission) (struct inode *, int);
int (*check_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
...
}
If your kernel has the same thing, then the function signature of your module_permission function is (struct inode *, int, struct nameidata *) where as .permission expects (struct inode *, int)

Resources