losing capabilities after setuid() - c

Trying to set cap_setgid,cap_setuid,cap_setpcap.
#include <sys/types.h>
#include <sys/capability.h>
int main()
{
cap_t caps;
caps = cap_get_proc();
cap_value_t cap_list[2];
cap_list[0] = CAP_SETUID;
cap_list[1] = CAP_SETGID;
cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET);
cap_set_flag(caps, CAP_INHERITABLE, 2, cap_list, CAP_SET);
cap_set_proc(caps);
cap_free(caps);
setgid(65534);
setuid(65534);
cap_get_proc();
setgid(0);
setuid(0);
return 0;
}
Execution is going under root user.
Tracing the program shows this
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(65534) = 0
setuid(65534) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, 0, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(0) = -1 EPERM (Operation not permitted)
setuid(0) = -1 EPERM (Operation not permitted)
exit_group(0) = ?
+++ exited with 0 +++
Privileges are set but do not work. Any suggestions how to solve this problem?
UPDATE: prctl added to code
21a22
> prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
24a26
> cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET);
so now it is
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
setgid(65534);
setuid(65534);
cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET);
Caps were inherited after setuid, and caps that were set manually are still there, but it didn't solve the problem
setgid(65534) = 0
setuid(65534) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0
setgid(0) = -1 EPERM (Operation not permitted)
setuid(0) = -1 EPERM (Operation not permitted)
exit_group(0) = ?
+++ exited with 0 +++
UPDATE2:
Can't understand it. Ive added 2strs after 1st setuid, to check out for caps.
printf("cape set %d\n", cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET));
printf("%s\n", cap_to_text(cap_get_proc(), NULL));
it returned
catp set 0
=p cap_setgid,cap_setuid,cap_setpcap+i
Effective flag is not set, but cap_set_flag returned 0

By default, capability sets are lost across an UID transition; use
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
to retain permitted capabilities (cap_set_flag(caps, CAP_PERMITTED, ...)). Note that the effective capability set will be reset, but can be re-established.
The following works fine for me.
#include <sys/capability.h>
#include <sys/prctl.h>
#include <unistd.h>
int main(int argc, char **argv) {
cap_value_t cap_values[] = {CAP_SETUID, CAP_SETGID};
cap_t caps;
caps = cap_get_proc();
cap_set_flag(caps, CAP_PERMITTED, 2, cap_values, CAP_SET);
cap_set_proc(caps);
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
cap_free(caps);
setgid(65534);
setuid(65534);
caps = cap_get_proc();
cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_values, CAP_SET);
cap_set_proc(caps);
cap_free(caps);
setgid(0);
setuid(0);
return 0;
}
$ sudo strace ./a.out
...
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
prctl(PR_SET_KEEPCAPS, 1) = 0
setgid(65534) = 0
setuid(65534) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_SETGID|CAP_SETUID, CAP_CHOWN|CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_FOWNER|CAP_FSETID|CAP_KILL|CAP_SETGID|CAP_SETUID|CAP_SETPCAP|CAP_LINUX_IMMUTABLE|CAP_NET_BIND_SERVICE|CAP_NET_BROADCAST|CAP_NET_ADMIN|CAP_NET_RAW|CAP_IPC_LOCK|CAP_IPC_OWNER|CAP_SYS_MODULE|CAP_SYS_RAWIO|CAP_SYS_CHROOT|CAP_SYS_PTRACE|CAP_SYS_PACCT|CAP_SYS_ADMIN|CAP_SYS_BOOT|CAP_SYS_NICE|CAP_SYS_RESOURCE|CAP_SYS_TIME|CAP_SYS_TTY_CONFIG|CAP_MKNOD|CAP_LEASE|CAP_AUDIT_WRITE|CAP_AUDIT_CONTROL|CAP_SETFCAP, 0}) = 0
setgid(0) = 0
setuid(0) = 0
...

I think you confused CAP_PERMITTED set with CAP_INHERITABLE,
Unless you are using threads/exec , you want to use CAP_PERMITTED.
Inheritable (formerly known as allowed):
This set is ANDed with the thread's inheritable set to determine which inheritable capabilities are enabled in the
permitted set of the thread after the execve(2)
As for update2: try printing out cap_to_text(cap_get_proc()) before/after and also consider what is the difference between cap_set_flag and cap_set_proc.

Related

How do I fix a CL_INVALID_MEM_OBJECT when I pass a buffer to an OpenCL kernel and the buffer is from clCreateFromGLTexture?

I need to do some math on the pixels of a GL texture. I have a working OpenCL kernel. I can convert the GL texture to an OpenCL buffer (at least, it doesn't give an error). But when I try to set that buffer as an argument to the kernel I get error -38 (CL_INVALID_MEM_OBJECT).
I originally tried it using rust, but when that was failing, I switched to C just to see if the problem existed independent of rust's wrappers.
This is my C app that is duct taped together from a couple of examples (c++ -g -o check2 check2.cxx -lOpenCL -lGL -lX11):
/*
https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <CL/cl.h>
#include <CL/cl_gl.h>
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
// Helper to check for extension string presence. Adapted from:
// http://www.opengl.org/resources/features/OGLextensions/
static bool isExtensionSupported(const char *extList, const char *extension)
{
const char *start;
const char *where, *terminator;
/* Extension names should not have spaces. */
where = strchr(extension, ' ');
if (where || *extension == '\0')
return false;
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
for (start=extList;;) {
where = strstr(start, extension);
if (!where)
break;
terminator = where + strlen(extension);
if ( where == start || *(where - 1) == ' ' )
if ( *terminator == ' ' || *terminator == '\0' )
return true;
start = terminator;
}
return false;
}
static bool ctxErrorOccurred = false;
static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
ctxErrorOccurred = true;
return 0;
}
void test_kernel(cl_mem a_mem_obj, cl_mem b_mem_obj, cl_mem c_mem_obj, cl_kernel kernel, int LIST_SIZE, cl_command_queue command_queue)
{
int err;
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj);
printf("err? %d\tset kernel arg 0\n", err);
err = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj);
printf("err? %d\n", err);
// Execute the OpenCL kernel on the list
size_t global_item_size = LIST_SIZE; // Process the entire lists
size_t local_item_size = 64; // Divide work items into groups of 64
err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
printf("err? %d\t(kernel diff)\n", err);
// Read the memory buffer C on the device to the local variable C
long long *C;
C= (long long*)malloc(sizeof(*C)*LIST_SIZE);
err = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0,
LIST_SIZE * sizeof(*C), C, 0, NULL, NULL);
printf("err? %d(copy result)\n", err);
for (int i=0; i<LIST_SIZE && i<10; i++) {
printf("%lld\n", C[i]);
}
free(C);
}
int main(int argc, char* argv[])
{
Display *display = XOpenDisplay(NULL);
if (!display)
{
printf("Failed to open X display\n");
exit(1);
}
// Get a matching FB config
static int visual_attribs[] =
{
GLX_X_RENDERABLE , True,
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
GLX_RENDER_TYPE , GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
GLX_RED_SIZE , 8,
GLX_GREEN_SIZE , 8,
GLX_BLUE_SIZE , 8,
GLX_ALPHA_SIZE , 8,
GLX_DEPTH_SIZE , 24,
GLX_STENCIL_SIZE , 8,
GLX_DOUBLEBUFFER , True,
//GLX_SAMPLE_BUFFERS , 1,
//GLX_SAMPLES , 4,
None
};
int glx_major, glx_minor;
// FBConfigs were added in GLX version 1.3.
if ( !glXQueryVersion( display, &glx_major, &glx_minor ) ||
( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
{
printf("Invalid GLX version");
exit(1);
}
printf( "Getting matching framebuffer configs\n" );
int fbcount;
GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
if (!fbc)
{
printf( "Failed to retrieve a framebuffer config\n" );
exit(1);
}
printf( "Found %d matching FB configs.\n", fbcount );
// Pick the FB config/visual with the most samples per pixel
printf( "Getting XVisualInfos\n" );
int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
int i;
for (i=0; i<fbcount; ++i)
{
XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] );
if ( vi )
{
int samp_buf, samples;
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES , &samples );
printf( " Matching fbconfig %d, visual ID 0x%2lx: SAMPLE_BUFFERS = %d,"
" SAMPLES = %d\n",
i, vi -> visualid, samp_buf, samples );
if ( best_fbc < 0 || samp_buf && samples > best_num_samp )
best_fbc = i, best_num_samp = samples;
if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
worst_fbc = i, worst_num_samp = samples;
}
XFree( vi );
}
GLXFBConfig bestFbc = fbc[ best_fbc ];
// Be sure to free the FBConfig list allocated by glXChooseFBConfig()
XFree( fbc );
#if 0
// Get a visual
XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc );
printf( "Chosen visual ID = 0x%lx\n", vi->visualid );
printf( "Creating colormap\n" );
XSetWindowAttributes swa;
Colormap cmap;
swa.colormap = cmap = XCreateColormap( display,
RootWindow( display, vi->screen ),
vi->visual, AllocNone );
swa.background_pixmap = None ;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
printf( "Creating window\n" );
Window win = XCreateWindow( display, RootWindow( display, vi->screen ),
0, 0, 100, 100, 0, vi->depth, InputOutput,
vi->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa );
if ( !win )
{
printf( "Failed to create window.\n" );
exit(1);
}
// Done with the visual info data
XFree( vi );
XStoreName( display, win, "GL 3.0 Window" );
printf( "Mapping window\n" );
XMapWindow( display, win );
#endif
// Get the default screen's GLX extension list
const char *glxExts = glXQueryExtensionsString( display,
DefaultScreen( display ) );
// NOTE: It is not necessary to create or make current to a context before
// calling glXGetProcAddressARB
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
GLXContext ctx = 0;
// Install an X error handler so the application won't exit if GL 3.0
// context allocation fails.
//
// Note this error handler is global. All display connections in all threads
// of a process use the same error handler, so be sure to guard against other
// threads issuing X commands while this code is running.
ctxErrorOccurred = false;
int (*oldHandler)(Display*, XErrorEvent*) =
XSetErrorHandler(&ctxErrorHandler);
// Check for the GLX_ARB_create_context extension string and the function.
// If either is not present, use GLX 1.3 context creation method.
if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
!glXCreateContextAttribsARB )
{
printf( "glXCreateContextAttribsARB() not found"
" ... using old-style GLX context\n" );
ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
}
// If it does, try to get a GL 3.0 context!
else
{
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
printf( "Creating context\n" );
ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
True, context_attribs );
// Sync to ensure any errors generated are processed.
XSync( display, False );
if ( !ctxErrorOccurred && ctx )
printf( "Created GL 3.0 context\n" );
else
{
// Couldn't create GL 3.0 context. Fall back to old-style 2.x context.
// When a context version below 3.0 is requested, implementations will
// return the newest context version compatible with OpenGL versions less
// than version 3.0.
// GLX_CONTEXT_MAJOR_VERSION_ARB = 1
context_attribs[1] = 1;
// GLX_CONTEXT_MINOR_VERSION_ARB = 0
context_attribs[3] = 0;
ctxErrorOccurred = false;
printf( "Failed to create GL 3.0 context"
" ... using old-style GLX context\n" );
ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
True, context_attribs );
}
}
// Sync to ensure any errors generated are processed.
XSync( display, False );
// Restore the original error handler
XSetErrorHandler( oldHandler );
if ( ctxErrorOccurred || !ctx )
{
printf( "Failed to create an OpenGL context\n" );
exit(1);
}
// Verifying that context is a direct context
if ( ! glXIsDirect ( display, ctx ) )
{
printf( "Indirect GLX rendering context obtained\n" );
}
else
{
printf( "Direct GLX rendering context obtained\n" );
}
printf( "Making context current\n" );
glXMakeCurrent( display, 0, ctx );
#define IMAGE_DIAM 512
#define LIST_SIZE (IMAGE_DIAM*IMAGE_DIAM*3)
GLuint texture_id;
{
glGenTextures(1, &texture_id);
printf("err? %d\n", glGetError());
glBindTexture(GL_TEXTURE_2D, texture_id);
printf("err? %d\t(bind texture)\n", glGetError());
unsigned char random_stack_crap[LIST_SIZE];
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, IMAGE_DIAM, IMAGE_DIAM, 0, GL_RGB, GL_UNSIGNED_BYTE, random_stack_crap);
printf("err? %d\n", glGetError());
}
//
//
//
cl_platform_id platform;
clGetPlatformIDs(1, &platform, NULL);
cl_device_id device;
clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
printf("device\t%p\n", device);
printf ("context\t%p\t%p\n", ctx, glXGetCurrentContext());
printf ("display\t%p\t%p\n", display, glXGetCurrentDisplay());
cl_context_properties props[] =
{
CL_GL_CONTEXT_KHR,
(cl_context_properties) glXGetCurrentContext(),
CL_GLX_DISPLAY_KHR,
(cl_context_properties) glXGetCurrentDisplay(),
CL_CONTEXT_PLATFORM,
(cl_context_properties) platform,
0
};
int err=0;
cl_context cl = clCreateContext(props, 1, &device, NULL, NULL, &err);
printf("err? %d\n", err);
printf("cl context %p\n", cl);
//
// https://www.eriksmistad.no/getting-started-with-opencl-and-gpu-computing/
//
cl_command_queue command_queue = clCreateCommandQueue(cl, device, 0, &err);
printf("err? %d\n", err);
printf("cl queue %p\n", command_queue);
// Create memory buffers on the device for each vector
cl_mem z_mem_obj = clCreateFromGLTexture( cl,
CL_MEM_READ_WRITE,
GL_TEXTURE_2D,
0,
texture_id,
&err);
cl_mem a_mem_obj = clCreateBuffer(cl, CL_MEM_READ_ONLY,
LIST_SIZE , NULL, &err);
printf("err? %d\n", err);
cl_mem b_mem_obj = clCreateBuffer(cl, CL_MEM_READ_ONLY,
LIST_SIZE , NULL, &err);
printf("err? %d\n", err);
cl_mem c_mem_obj = clCreateBuffer(cl, CL_MEM_WRITE_ONLY,
LIST_SIZE*8 , NULL, &err);
printf("err? %d\n", err);
// Copy the lists A and B to their respective memory buffers
{
unsigned char *A = (unsigned char*) malloc(LIST_SIZE);
for (int i=0; i<LIST_SIZE; i++) {
A[i] = i+2;
}
unsigned char *B = (unsigned char*) malloc(LIST_SIZE);
for (int i=0; i<LIST_SIZE; i++) {
B[i] = 2*i;
}
err = clEnqueueWriteBuffer(command_queue, a_mem_obj, CL_TRUE, 0,
LIST_SIZE, A, 0, NULL, NULL);
printf("err? %d\tcopy A\n", err);
err = clEnqueueWriteBuffer(command_queue, b_mem_obj, CL_TRUE, 0,
LIST_SIZE, B, 0, NULL, NULL);
printf("err? %d\tcopy B\n", err);
}
const char* source_str = "__kernel void diff(__global uchar* rgb_a, __global uchar* rgb_b, __global ulong * diff_out)\n\
{\n\
int idx = get_global_id(0);\n\
diff_out[idx] = abs((int)rgb_a[idx] - (int)rgb_b[idx]);\n\
}";
size_t source_size = strlen(source_str);
// Create a program from the kernel source
cl_program program = clCreateProgramWithSource(cl, 1,
(const char **)&source_str, (const size_t *)&source_size, &err);
printf("err? %d\t(create program)\n", err);
// Build the program
err = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
printf("err? %d\n", err);
// Create the OpenCL kernel
cl_kernel kernel = clCreateKernel(program, "diff", &err);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&a_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&b_mem_obj);
printf("err? %d\n", err);
err = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&c_mem_obj);
printf("err? %d\n", err);
// Execute the OpenCL kernel on the list
size_t global_item_size = LIST_SIZE; // Process the entire lists
size_t local_item_size = 64; // Divide work items into groups of 64
err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
printf("err? %d\t(kernel diff)\n", err);
// Read the memory buffer C on the device to the local variable C
long long *C;
C= (long long*)malloc(sizeof(*C)*LIST_SIZE);
err = clEnqueueReadBuffer(command_queue, c_mem_obj, CL_TRUE, 0,
LIST_SIZE * sizeof(*C), C, 0, NULL, NULL);
printf("err? %d(copy resul)\n", err);
for (int i=0; i<LIST_SIZE && i<10; i++) {
printf("%lld\n", C[i]);
}
free(C);
test_kernel(a_mem_obj, b_mem_obj, c_mem_obj, kernel, LIST_SIZE, command_queue);
test_kernel(z_mem_obj, b_mem_obj, c_mem_obj, kernel, LIST_SIZE, command_queue);
return 0;
}
The output on my linux/gentoo box with mesa-progs-8.4.0 is
Getting matching framebuffer configs
Found 10 matching FB configs.
Getting XVisualInfos
Matching fbconfig 0, visual ID 0x24: SAMPLE_BUFFERS = 0, SAMPLES = 0
Matching fbconfig 1, visual ID 0x7a: SAMPLE_BUFFERS = 0, SAMPLES = 0
Matching fbconfig 2, visual ID 0x38: SAMPLE_BUFFERS = 1, SAMPLES = 2
Matching fbconfig 3, visual ID 0x8e: SAMPLE_BUFFERS = 1, SAMPLES = 2
Matching fbconfig 4, visual ID 0x3a: SAMPLE_BUFFERS = 1, SAMPLES = 4
Matching fbconfig 5, visual ID 0x90: SAMPLE_BUFFERS = 1, SAMPLES = 4
Matching fbconfig 6, visual ID 0x44: SAMPLE_BUFFERS = 1, SAMPLES = 8
Matching fbconfig 7, visual ID 0x9a: SAMPLE_BUFFERS = 1, SAMPLES = 8
Matching fbconfig 8, visual ID 0x4c: SAMPLE_BUFFERS = 1, SAMPLES = 16
Matching fbconfig 9, visual ID 0xa2: SAMPLE_BUFFERS = 1, SAMPLES = 16
Creating context
Created GL 3.0 context
Direct GLX rendering context obtained
Making context current
err? 0
err? 0 (bind texture)
err? 0
device 0x557c1755cef0
context 0x557c173e0b68 0x557c173e0b68
display 0x557c172ee950 0x557c172ee950
err? 0
cl context 0x557c17559340
err? 0
cl queue 0x557c177dd080
err? 0
err? 0
err? 0
err? 0 copy A
err? 0 copy B
err? 0 (create program)
err? 0
err? 0
err? 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy resul)
2
1
0
1
2
3
4
5
6
7
err? 0 set kernel arg 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy result)
2
1
0
1
2
3
4
5
6
7
err? -38 set kernel arg 0
err? 0
err? 0
err? 0 (kernel diff)
err? 0(copy result)
2
1
0
1
2
3
4
5
6
7
Notice the err? -38 set kernel arg 0 which corresponds to the final test where I pass z_mem_obj to use the buffer converted from a GL texture.
clinfo | grep khr lists cl_khr_gl_sharing in the Platform Extensions and Device Extensions.

gdb: cascaded signal. info on outer one - HOWTO

Following program generates SIGSEGV from within SIGUSR1 signal handler.
#include <signal.h>
#include <unistd.h>
#include <iostream>
void sigusr_handler(int sig_number)
{
std::cout << "hallo" << "\n";
char *a = (char*)0x0;
char b = *a;
std::cout << b << "\n";
}
struct sigaction my_action;
int main(int argc, char *argv[])
{
my_action.sa_handler = sigusr_handler;
sigaction(SIGUSR1, &my_action, nullptr);
sleep(1000);
return 0;
}
Let's run program in gdb then send SIGUSR1 to the program.
siginfo looks like following
(gdb) p $_siginfo
$8 = {
si_signo = 11,
si_errno = 0,
si_code = 1,
_sifields = {
_pad = {0, 0, -1814214640, 21880, -1601342336, 32766, -1848922720, 21880, -1811928400, 21880, 0, 0, -1811928400, 21880, 176, 0, -1840786848, 21880, -1847783957, 21880, -1811928400, 21880, -1840786848, 21880, -1814214640, 21880, -1845891081, 21880},
_kill = {
si_pid = 0,
si_uid = 0
},
_timer = {
si_tid = 0,
si_overrun = 0,
si_sigval = {
sival_int = -1814214640,
sival_ptr = 0x557893dd4810
}
},
_rt = {
si_pid = 0,
si_uid = 0,
si_sigval = {
sival_int = -1814214640,
sival_ptr = 0x557893dd4810
}
},
_sigchld = {
si_pid = 0,
si_uid = 0,
si_status = -1814214640,
si_utime = -6877712962820221576,
si_stime = -7941062615231332354
},
_sigfault = {
si_addr = 0x0,
_addr_lsb = 93976365189136,
_addr_bnd = {
_lower = 0x7ffea08d7480,
_upper = 0x557891cbada0
}
},
_sigpoll = {
si_band = 0,
si_fd = -1814214640
}
}
}
Question: is it possible to "guess" from gdb session, that outer signal was SIGUSR1?
regards,
Mat
NOTE TO STACKOVEFLOW: I have no idea what usefull notes I need to add to the above in order to have the question more usefull - IMO: more text makes the question blurred, but I'm adding some notes because I'm getting information:
"It looks like your post is mostly code; please add some more details" otherwise.
READERS OF POST: PLEASE FORGIVE ME.
END OF NOTE TO STACKOVERFLOW
is it possible to "guess" from gdb session, that outer signal was SIGUSR1
Yes:
hallo
Program received signal SIGSEGV, Segmentation fault.
0x00005555555551be in sigusr_handler (sig_number=10) at t.c:9
9 char b = *a;
(gdb) bt
#0 0x00005555555551be in sigusr_handler (sig_number=10) at t.c:9
#1 <signal handler called>
#2 0x00007ffff775cff4 in __GI___nanosleep (requested_time=requested_time#entry=0x7fffffffdb70, remaining=remaining#entry=0x7fffffffdb70)
at ../sysdeps/unix/sysv/linux/nanosleep.c:28
#3 0x00007ffff775cf2a in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#4 0x0000555555555225 in main (argc=1, argv=0x7fffffffdca8) at t.c:20
From this, you can clearly see that the program received SIGSEGV while in the handler for signal 10, which is SIGUSR1.
P.S. It's unclear how this question even arises: GDB should have earlier stopped and told you that SIGUSR1 was received, like so:
Program received signal SIGUSR1, User defined signal 1.
0x00007ffff775cff4 in __GI___nanosleep (requested_time=requested_time#entry=0x7fffffffdb70, remaining=remaining#entry=0x7fffffffdb70) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.

Failed to check against Nt Authority\System SID

I have a process which can be spawned by a service with either NT AUTHORITY\Network Service or NT AUTHORITY\System, and i need to check for it. So i have written a code like this:
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)) {
GetTokenInformation(hToken, 1, 0, 0, &dwOut);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
hTokenUser = (TOKEN_USER*)malloc( dwOut );
if (!GetTokenInformation(hToken, TokenUser, hTokenUser, dwOut, &dwOut))
return false;
}
else
return false;
PSID psid = NULL;
SID_IDENTIFIER_AUTHORITY ntAuth = SECURITY_NT_AUTHORITY;
AllocateAndInitializeSid(&ntAuth, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psid);
if (EqualSid(psid, hTokenUser->User.Sid)) {
bResult = TRUE;
}
}
So what i do, i get current process token, and i get a SID from it using GetTokenInfo then i create the NT_AUTHORITY\System SID, using AllocateAndInitializeSid, and i compare two values together, however, it never works, when the process is run under NT_AUTHORITY\System check is always failing. Is this the correct way to get NT_AUTHORITY\System SID and compare it with the process sid?
Your code leaks handles and memory but it does provide the correct result on my machine. It might be different on your system so it would really help if you print out the result and GetLastError of every function call to help you debug. You should also code your function so you can tell the difference between errors and a negative (successful) result.
HRESULT isSystemUser()
{
HRESULT hr = E_FAIL;
HANDLE hToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
TOKEN_USER *pTU = NULL;
DWORD dwOut;
GetTokenInformation(hToken, TokenUser, 0, 0, &dwOut);
hr = HRESULT_FROM_WIN32(GetLastError());
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
pTU = (TOKEN_USER*) malloc(dwOut), hr = E_OUTOFMEMORY;
if (pTU)
{
if (GetTokenInformation(hToken, TokenUser, pTU, dwOut, &dwOut))
{
PSID psid = NULL;
SID_IDENTIFIER_AUTHORITY ntAuth = SECURITY_NT_AUTHORITY;
if (AllocateAndInitializeSid(&ntAuth, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psid))
{
hr = EqualSid(psid, pTU->User.Sid) ? S_OK : S_FALSE;
FreeSid(psid);
}
else
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
hr = HRESULT_FROM_WIN32(GetLastError());
free(pTU);
}
CloseHandle(hToken);
}
else
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
...
printf("isSystemUser=%d\n", isSystemUser()); // 0 = true, 1 = false, < 0 = error
and when running it:
C:\windows\system32>c:\test.exe
isSystemUser=0
C:\windows\system32>whoami
nt authority\system
Is it possible that you are not actually running as the real System user? What does ConvertSidToStringSid return for your TokenUser?

X Toolkit: heap is growing when recreating widgets

I'm trying to understand why the following program is leaking memory. When I look at the heap size by using the command more /proc/<pid>/smaps, I can see that the heap is only growing. It seems that the XtDestroyWidget is not really freeing up the memory. I would be very grateful if somebody can tell me why this is happening and show me the right way of recreating widgets.
Thanks in advance!
/* Compile on Solaris: cc widgets_mem.c -lXm -lXt -lX11 */
/* Compile on Linux: gcc -m32 widgets_mem.c -lXm -lXt -lX11 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysymdef.h>
#include <Xm/MainW.h>
#include <Xm/PushB.h>
#include <Xm/Form.h>
Widget toplevel;
Widget w_main;
Widget w_bb;
Widget w_button = NULL;
Window root_win;
XtAppContext app;
int screen_number;
Display *display = NULL;
void recreateWidgets ()
{
printf ("recreating widgets\n");
XtDestroyWidget (w_button);
w_button = XtVaCreateManagedWidget (
"button",
xmPushButtonWidgetClass, w_bb,
XmNfillOnArm, False,
XmNhighlightThickness, 0,
XmNborderWidth, 1,
XmNmarginTop, 1,
XmNmarginWidth, 2,
XmNmarginHeight, 0,
XmNwidth, 20,
XmNheight, 10,
XmNrecomputeSize, False,
XmNalignment, XmALIGNMENT_CENTER,
NULL);
}
void main (int argc, char **argv)
{
XEvent event;
toplevel = XtVaAppInitialize (&app, "Mem leak test",
NULL, 0, &argc, argv, NULL, NULL);
display = XtDisplay (toplevel);
screen_number = DefaultScreen (display);
root_win = RootWindow (display, screen_number);
w_main = XtVaCreatePopupShell (
"main",
topLevelShellWidgetClass, toplevel,
XmNgeometry, "-0+0",
XmNborderWidth, 0,
XmNshadowThickness, 0,
XmNminWidth, 1,
XmNmwmDecorations, 0,
XmNmwmFunctions, 0,
XmNwidth, 600,
XmNheight, 200,
NULL);
w_bb = XtVaCreateManagedWidget (
"",
xmBulletinBoardWidgetClass, w_main,
XmNborderWidth, 4,
XmNshadowThickness, 0,
XmNmarginWidth, 0,
XmNmarginHeight, 0,
XmNx, 0,
XmNy, 0,
XmNwidth, 500,
XmNheight, 100,
NULL);
w_button = XtVaCreateManagedWidget (
"button",
xmPushButtonWidgetClass, w_bb,
XmNfillOnArm, False,
XmNhighlightThickness, 0,
XmNborderWidth, 1,
XmNmarginTop, 1,
XmNmarginWidth, 2,
XmNmarginHeight, 0,
XmNwidth, 20,
XmNheight, 10,
XmNrecomputeSize, False,
XmNalignment, XmALIGNMENT_CENTER,
NULL);
XtPopup (w_main, XtGrabNone);
while (1)
{
XtAppNextEvent (app, &event);
if (event.type == ButtonPress)
{
printf ("Button pressed, recreating widgets\n");
recreateWidgets();
}
}
}
I found the bug in my code: I had to add a XtDispatchEvent(&event), which handles the deallocating of the widgets which are on the destory list, an internal list in Xt.

Functions of Allegro 4 in Allegro 5

I have a code written in Allegro 4 and am converting it to Allegro 5, but I'm having serious problems with functions that no longer exist in allegro 5, one of them is "blit"
BITMAP *bTile; // Bitmap do tile;
BITMAP *bMapa; // Bitmap do mapa;
BITMAP *bTexturas[20]; // Vetor de bitmap das texturas;
BITMAP *bChar; // Bitmap do personagem;
BITMAP *bMario[3];
// ##########################################################
int main()
{
int vResolucao_x = 640;
int vResolucao_y = 480;
init(vResolucao_x, vResolucao_y);
BITMAP *buffer = create_bitmap(vResolucao_x, vResolucao_y);
bTile = load_bitmap("Tiles/tile.bmp", NULL);
bChar = load_bitmap("Tiles/mario.bmp", NULL);
bMapa = create_bitmap(vResolucao_x, vResolucao_y);
// ############# - Carrega imagens do mario - ############
bMario[0] = create_bitmap(vTile,vTile);
bMario[1] = create_bitmap(vTile,vTile);
bMario[2] = create_bitmap(vTile,vTile);
blit(bChar, bMario[0], 0, 0, 0, 0, vTile, vTile);
blit(bChar, bMario[1], 33, 0, 0, 0, vTile, vTile);
blit(bChar, bMario[2], 66, 0, 0, 0, vTile, vTile);
// #######################################################
install_int(fGravidade,5);
fCarrega_Sprites_Mapa();
fCarrega_Mapa();
fMostra_Mapa();
draw_sprite(screen, bMapa, 0, 0 );
while (!key[KEY_ESC]) {
Virtually nothing of this my old code works with Allegro 5, so I'm doing the conversion as I can learn, but this blit function, can not find its like in allegro 5, another function that I can not find your simulate is: install_int (...)
Allegro 5 is essentially a completely new library. Here's a line-by-line translation, as best as can be done. Note that Allegro 5 uses a fundamentally different concept (event loop) and you should really take the time to learn how that works before diving into trying to convert your code.
ALLEGRO_BITMAP *bMario[3];
// ##########################################################
int main()
{
int vResolucao_x = 640;
int vResolucao_y = 480;
init(vResolucao_x, vResolucao_y);
ALLEGRO_BITMAP *buffer = al_create_bitmap(vResolucao_x, vResolucao_y);
bTile = al_load_bitmap("Tiles/tile.bmp");
bChar = al_load_bitmap("Tiles/mario.bmp");
bMapa = al_create_bitmap(vResolucao_x, vResolucao_y);
// ############# - Carrega imagens do mario - ############
bMario[0] = al_create_bitmap(vTile,vTile);
bMario[1] = al_create_bitmap(vTile,vTile);
bMario[2] = al_create_bitmap(vTile,vTile);
al_set_target_bitmap(bMario[0]);
al_draw_bitmap(bchar, 0, 0, 0);
al_set_target_bitmap(bMario[1]);
al_draw_bitmap(bchar, 33, 0, 0);
al_set_target_bitmap(bMario[2]);
al_draw_bitmap(bchar, 66, 0, 0);
al_set_target_backbuffer(display);
// #######################################################
fGravidade = al_create_timer(5 / 1000.0); // ALLEGRO_TIMER*
ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue();
al_register_event_source(queue, al_get_timer_event_source(gfGravidade));
al_register_event_source(queue, al_get_keyboard_event_source());
fCarrega_Sprites_Mapa();
fCarrega_Mapa();
fMostra_Mapa();
al_draw_bitmap(bMapa, 0, 0, 0);
al_flip_display();
while (true) {
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
if (event.type == ALLEGRO_EVENT_TIMER) {
// fGravidade ticked
}
else if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
break;
}
}
}

Resources