I want to send messages from a kernel extension into a userland program using kernel controls. I'm experiencing an EINVAL error when calling ctl_enqueuedata.
I've set up a Kernel Control and I'm trying to send messages through it using ctl_enqueuedata. I'm setting
ep_ctl.ctl_flags = 0
before passing to ctl_register, which, the documents suggest, should result in ctl_unit being automatically set.
To quote kern_control.h:
For a dynamically assigned control ID, do not set the CTL_FLAG_REG_ID_UNIT flag.
static struct kern_ctl_reg ep_ctl;
static kern_ctl_ref kctlref;
...
errno_t error;
bzero(&ep_ctl, sizeof(ep_ctl)); // sets ctl_unit to 0
ep_ctl.ctl_id = 0;
ep_ctl.ctl_unit = 0;
strncpy(ep_ctl.ctl_name, CONTROL_NAME, strlen(CONTROL_NAME));
ep_ctl.ctl_flags = 0x0; // not CTL_FLAG_REG_ID_UNIT so unit gets supplied. Not CTL_FLAG_PRIVILEGED either.
ep_ctl.ctl_send = EPHandleSend;
ep_ctl.ctl_getopt = EPHandleGet;
ep_ctl.ctl_setopt = EPHandleSet;
ep_ctl.ctl_connect = EPHandleConnect;
ep_ctl.ctl_disconnect = EPHandleDisconnect;
error = ctl_register(&ep_ctl, &kctlref);
printf("setupControl %d\n", error);
When I call ctl_register it returns 0 ok.
When I call ctl_enqueuedata, passing in my struct kern_ctl_reg I'm getting 22, which is EINVAL. One of those arguments appears to be incorrect. The other arguments I'm passing are a static test string and its length for data, and zero flags.
int result = ctl_enqueuedata(kctlref, ep_ctl.ctl_unit, filename, length, 0x0);
The value of my ep_ctl's .ctl_unit is 0, the value of .ctl_id is 6. Could it be that the ctl_unit value being passed to ctl_enqueuedata is invalid / un-initialized?
kern_control.h says of ctl_unit:
This field is ignored for a dynamically assigned control ID
Which suggests that it isn't required anyway?
Have I missed something in initializing my ep_ctl?
I believe you supply wrong value as the 2nd parameter of ctl_enqueuedata(). Instead of ep_ctl.ctl_unit, you have to remember struct sockaddr_ctl::sc_unit in the EPHandleConnect() callback and that's what you are supposed to pass into ctl_enqueuedata().
I suggest using OSX's kernel debugging facilities to figure out what's going on here. That will let you walk through the relevant kernel code, and should tell you where it's rejecting your input.
Related
Given the following code how can I convert the v8::Local<v8::Value> into a uint32_t. Or other types based on the Is* method?
v8::Local<v8::Value> value;
v8::Local<v8::Context> context = v8::Context::New(v8::Isolate::GetCurrent());
if(value->IsUint32()) {
v8::MaybeLocal<Int32> maybeLocal = value->Uint32Value(context);
uint32_t i = maybeLocal;
}
Your posted code doesn't work because value->Uint32Value(context) doesn't return a v8::MaybeLocal<Int32>. C++ types are your friend (just like TypeScript)!
You have two possibilities:
(1) You can use Value::Uint32Value(...) which returns a Maybe<uint32_t>. Since you already checked that value->IsUint32(), this conversion cannot fail, so you can extract the uint32_t wrapped in the Maybe using Maybe::ToChecked().
(2) You can use Value::ToUint32(...) which returns a MaybeLocal<Uint32>. Again, since you already checked that value->IsUint32(), that cannot fail, so you can get a Local<Uint32> via MaybeLocal::ToLocalChecked(), and then simply use -> syntax to call the wrapped Uint32's Value() method, which gives a uint32_t.
If you're only interested in the final uint32_t (and not in the intermediate Local<Uint32>, which you could pass back to JavaScript), then option (1) will be slightly more efficient.
Note that IsUint32() will say false for objects like {valueOf: () => 42; }. If you want to handle such objects, then attempt the conversion, and handle failures, e.g.:
Maybe<uint32_t> maybe_uint = value->Uint32Value(context);
if (maybe_uint.IsJust()) {
uint32_t i = maybe_uint.FromJust();
} else {
// Conversion failed. Maybe it threw an exception (use a `v8::TryCatch` to catch it), or maybe the object wasn't convertible to a uint32.
// Handle that somehow.
}
Also, note that most of these concepts are illustrated in V8's samples and API tests. Reading comments and implementations in the API headers themselves also provides a lot of insight.
Final note: you'll probably want to track the current context you're using, rather than creating a fresh context every time you need one.
Now I'm trying to show a progressbar dialog while reading and processing a file, but my code throws "read access violation" on closing the dialog.
Exact error message is,
**__pUnknown** was 0xFFFFFFFFFFFFFFFF.
And below is my code.
void LoadFile(StorageFile^ file) {
ContentDialog^ loaderDialog = ref new ContentDialog();
loaderDialog->Title = L"Loading...";
loaderDialog->Content = ref new ProgressBar();
loaderDialog->ShowAsync();
Concurrency::create_task(FileIO::ReadTextAsync(file))
.then([&](Platform::String^ fileText) {
// File processing parts are omitted.
// ...
loaderDialog->Hide(); // Read access violation!
}
);
}
Why this becomes an error?
From: https://devblogs.microsoft.com/cppblog/ccx-part-2-of-n-types-that-wear-hats/
So, what exactly is a ^ type? A hat type is a smart pointer type that
(1) automatically manages the lifetime of a Windows Runtime object and
(2) provides automatic type conversion capabilities to simplify use of
Windows Runtime objects.
You are taking a ref to the smart pointer, hence you are not increasing its reference count, see https://learn.microsoft.com/en-us/windows/win32/com/rules-for-managing-reference-counts .
This means that when the continuation is executed the reference is dangling.
You can try capturing by value [=] instead of reference [&].
Please note that you should consider, in the capture, capturing each variable instead of using [=] or [&]
I want to know the time when a disk is made offline by user. Is there a way to know this through WMI classes or other ways?
If you cannot find a way to do it through the Win32 API/WMI or other, I do know of an alternate way which you could look into as a last-resort.
What about using NtQueryVolumeInformationFile with the FileFsVolumeInformation class? You can do this to retrieve the data about the volume and then access the data through the FILE_FS_VOLUME_INFORMATION structure. This includes the creation time.
At the end of the post, I've left some resource links for you to read more on understanding this so you can finish it off the way you'd like to implement it; I do need to quickly address something important though, which is that the documentation will lead you to
an enum definition for the _FSINFOCLASS, but just by copy-pasting it from MSDN, it probably won't work. You need to set the first entry of the enum definition to 1 manually, otherwise it will mess up and NtQueryVolumeInformationFile will return an error status of STATUS_INVALID_INFO_CLASS (because the first entry will be identified as 0 and not 1 and then all the entries following it will be -1 to what they should be unless you manually set the = 1).
Here is the edited version which should work.
typedef enum _FSINFOCLASS {
FileFsVolumeInformation = 1,
FileFsLabelInformation,
FileFsSizeInformation,
FileFsDeviceInformation,
FileFsAttributeInformation,
FileFsControlInformation,
FileFsFullSizeInformation,
FileFsObjectIdInformation,
FileFsDriverPathInformation,
FileFsVolumeFlagsInformation,
FileFsSectorSizeInformation,
FileFsDataCopyInformation,
FileFsMetadataSizeInformation,
FileFsMaximumInformation
} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
Once you've opened a handle to the disk, you can call NtQueryVolumeInformationFile like this:
NTSTATUS NtStatus = 0;
HANDLE FileHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock = { 0 };
FILE_FS_VOLUME_INFORMATION FsVolumeInformation = { 0 };
...
Open the handle to the disk here, and then check that you have a valid handle.
...
NtStatus = NtQueryVolumeInformationFile(FileHandle,
&IoStatusBlock,
&FsVolumeInformation,
sizeof(FILE_FS_VOLUME_INFORMATION),
FileFsVolumeInformation);
...
If NtStatus represents an NTSTATUS error code for success (e.g. STATUS_SUCCESS) then you can access the VolumeCreationTime (LARGE_INTEGER) field of the FILE_FS_VOLUME_INFORMATION structure with the FsVolumeInformation variable.
Your final task at this point will be using the LARGE_INTEGER field named VolumeCreationTime to gather proper time/date information. There are two links included at the end of the post which are focused on that topic, they should help you sort it out.
See the following for more information.
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-ntqueryvolumeinformationfile
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ne-wdm-_fsinfoclass
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/ns-ntddk-_file_fs_volume_information
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724280.aspx
https://blogs.msdn.microsoft.com/joshpoley/2007/12/19/datetime-formats-and-conversions/
I have a proto schema defined as below,
message User {
int64 id = 1;
bool email_subscribed = 2;
bool sms_subscribed = 3;
}
Now as per official proto3 documentation, default values are not serialized to save space during wire transmission. But in my case I want to receive whether the client has explicitly set true/false for fields email_subscribed/sms_subscribed (because the values were true before but now the user wants to unsubscribe). Hence, when the client sends false for any of these fields, the generator code serializer just omits these fields.
How do I achieve this and avoid the omission of these fields for the above scenario?
PS: I am using Javascript as my GRPC client and Python and GRPC Server.
Update: this has changed recently with the re-introduction of presence tracking info proto3 via a new meaning of the optional keyword:
message User {
optional int64 id = 1;
optional bool email_subscribed = 2;
optional bool sms_subscribed = 3;
}
With this change (now available in protoc etc), explicit assignment is transmitted even if it is the implicit default value.
You cannot under proto3. Your best bet is probably to define a tri-bool enum with not-specified as the first item with value zero, and some true / false values after that.
This will require the same space as a protobuf bool, but will not be binary compatible - so you cannot simply change the declared member type on existing messages. Well, I guess if you make true === 1, then at least that still works - and for the transition you'd have to anticipate false / not specified being ambiguous until you've flushed any old data.
The other option is to add a bool fooSpecified member for every bool foo, but that takes more space and is error-prone due to being manual.
Another option will be to use wrappers with proto3. They basically wrap your value in a message so on the parent message it can be left null.
This way you can differentiate null / false / true on your bool field with a some extra work.
I have this declared above:
char PandaImage[] = "images/panda.png";
SDL_Texture* PandaTexture = nullptr;
I have a function to create textures:
void LoadMedia( SDL_Texture *ThisTexture, char *Image )
{
SDL_Surface* TempSurface = nullptr;
.......................
ThisTexture = SDL_CreateTextureFromSurface( gRenderer, TempSurface );
I call it as:
LoadMedia( PandaTexture, PandaImage );
It builds, logs the image loaded and texture created, but no image
If I hard change the line ( use Panda directly instead of This ):
PandaTexture = SDL_CreateTextureFromSurface( gRenderer, TempSurface );
My image is there.
I have always had trouble with & * and passing.
Is there a good, simple help for me?
Thanks for your kind help - back to Google for now
In short, I think you could solve your problem by changing the function to:
void LoadMedia( SDL_Texture** thisTexture, char* Image)
{
...
(*thisTexture) = SDL_CreateTextureFromSurface( gRenderer, TempSurface);
}
And by calling the function using:
LoadMedia( &PandaTexture, PandaImage);
An explanation:
Variables and Pointers
A variable is used to store data (a primitive or a class instance). For example:
int a = 10;
stores an integer in memory. This means, that symbol 'a' now represents number 10, which is stored somewhere in your computer's memory as 4 bytes.
A pointer is used to store an address (this address points towards a variable). For example:
int* a_address = 1234;
says that there is an integer stored at address 1234 in your computer's memory. A pointer always takes up the same amount of space (4 bytes on a 32 bit machine and 8 bytes on a 64 bit machine), as it simply stores an address.
Getting the Address of a Variable [&]
You will rarely ever set the address of a pointer yourself. Often, pointers are the result of a "new" call. Using "new" reserves memory to store an instance of the class you want to create, and returns the address of the object. In essence, it says: "I created an object for you, and you can find it at this location in your memory".
Alternatively, when you have a normal variable (primitive of class instance), you can find its address by using the & character. For example:
int a = 10;
int* a_address = &a;
says: "store the location of variable a in pointer a_address. Why would you do this? Say you have a very large instance (for example an SDL_Texture consisting of many, many pixels) and you want to pass it to a function (or pass it back outside of the function). If you were to pass it to the function as SDL_Texture thisTexture, you are copying the entire object (a so-called pass by value). This is time consuming. Alternatively, you could simply pass the address to the function, as an SDL_Texture * thisTexture. This is a so called pass by reference, and it is much faster as you can imagine.
Getting the Variable at an Address [*]
Obviously, if you have an address, you also need a way to get the actual variable at that address. This is done using the * character. It is called "dereferencing". For example:
int a = 10;
int* a_address = &a;
int b = (*a_address);
This last line says: "Give me the variable, stored at address a_address, and put it in b".
Function Parameters Going Out-of-scope
When a function ends, its local variables (including parameters) go out-of-scope. This means that their memory is freed (for variables, not for dynamically allocated objects stored as pointers!). Their values will be forgotten. In your case, you are passing an SDL_Texture * as a parameter. This means, a copy is made of the address stored in PandaTexture. This address is copied over to thisTexture. You then write the return value of SDL_CreateTextureFromSurface to thisTexture. Next the function ends, and thisTexture goes out-of-scope. As a result, the location of your SDL_Texture (the SDL_Texture * pointer) is lost forever. You actually want to store the address to pointer PandaTexture, but as you can see, the address is only written to thisTexture.
Solution: How to Fix your Function
We can fix this by passing a pointer, to your pointer called PandaTexture. A "pointer to a pointer" is written as:
SDL_Surface** thisTexture;
We want to pass the address of pointer PandaTexture to this. This way, we can write to PandaTexture from inside your method! After all, we know where PandaTexture stores its pointer in memory, allowing us to change it. To actually put the address of PandaTexture in it, we need to use the & character in the function call as such:
LoadMedia(&PandaTexture, PandaImage);
Next, inside of our function, we want to change the value of PandaTexture. However, we were passed &PandaTexture and not PandaTexture itself. To write the value of &PandaTexture (the address where our texture will be stored), we need dereferencing, as such:
(*thisTexture) = SDL_CreateTextureFromSurface(gRenderer, TempSurface);
This works because: "thisTexture is a pointer to a pointer to an SDL_Texture (aka an SDL_Texture**). By dereferencing it, we obtain a pointer to an SDL_Texture (aka an SDL_Texture*). Here we can store the return value of the SDL_CreateTextureFromSurface function.
Why do we not run into out-of-scope issues here? Parameter thisTexture will still go out of scope, and its value will be forgotten. But! We didn't write to thisTexture, instead we wrote our SDL_Texture * pointer to the address that thisTexture points to! This bit of memory is not cleared due to scoping, so we can view the results from outside the function!
In summary, you can solve your problem using a pointer to a pointer. I hope the above clears up the concepts of pointers, variables, addresses and dereferencing a bit!